react-native-reanimated-bottom-sheet
react-native-reanimated-bottom-sheet copied to clipboard
Re-render breaks onOpenEnd and onCloseStart
Hi, I have callbacks for onOpenEnd and onCloseStart that will cause to state change on the parent component but the problem is after the first call these two methods will not be called anymore, if I remove the setState it will work as normal.
I have the same issue. For me onOpenStart nad onOpenEnd events are not always firing after upgrade to react-native 0.61.5 and react-native-navigation: 3.7.0. I have the latest 1.0.0-alpha.19 version of bottom sheet.
Same here.
Any news?
if you pass all the events to the bottomsheet it works well although it isn't a clean approach but for now it fixes the problem.
<BottomSheet ref={this.bs} initialSnap={1} enabledBottomInitialAnimation onOpenStart={(): void => {}} onOpenEnd={this.sheetOpenEnd} onCloseStart={this.sheetCloseStart} onCloseEnd={(): void => {}} callbackNode={this.fall} snapPoints={this.snapPoints} renderContent={(): React.ReactNode => this.props.children} renderHeader={this.renderHeader} />
@adoniscoder Sadly, it doesn't work for me :(
onCloseEnd
really needs a fix, especially on iOS #136 . @osdnk
@stachu2k, if it's still relevant try using the patched version I posted in #136 . It puts all my open/close events in order. The code is also available via this gist ReanimatedBottomSheet_patched.js.
@stachu2k, if it's still relevant try using the patched version I posted in #136 . It puts all my open/close events in order. The code is also available via this gist ReanimatedBottomSheet_patched.js.
Can you create a pull request?
-- edit --
The patch works perfect!
@karimcambridge I’m glad it helps.
As for the pull request, I assume that usually PR is a fix or an addition to the original code. I can see the part of the original code for the event handlers and would love to PR a fix, but as I said before I’m not sure I’d be able to make enough time at the moment for digging into it so that other things won’t be broken.
Also I use hooks which, as I guess, is not what the original code is based on. Another complication.
So a small nice and clean patch wrapper looks like a way to go.
@karimcambridge , @osdnk I think for the fix it's safe to use Animated
conditions from the patch I posted. I guess this part may be tricky so the sketch I helped myself with may be useful.
@yzalvov using the patch solved the issue here! Thanks!
The issue is not solved yet!
Hi @jerearaujo03 , I guess you've managed to pass props to my patched version ReanimatedBottomSheet_patched.js?
Yes! It works well (maybe there is a small delay when executing onOpenStart
), but it works
Hi @jerearaujo03
You may try to pass in callbackThreshold
prop as less than 0.01 (which is the default value) and check if onOpenStart
fires sooner.
For more details consult line 36 of the patch. The bottomTippingPoint
is defined there.
Yes, i've already tried but it doesn't worked. Likewise it works very well
@yzalvov your patch almost works for me. There is an issue when you swipe very quickly and for some reason, only handleOpenEnd
is called then, so not handleOpenStart
. I fixed this by adding
function handleOpenEnd() {
isCloseEndAllowed.current = true;
if (onOpenEnd) onOpenEnd();
}
below the handleOpenStart
function and changed the line () => onOpenEnd && onOpenEnd()
to handleOpenEnd
.
Let me know if that makes sense
@danieltovesson hi there. It'd make sense only if it'd work. I guess it doesn't. Because nothing changed in your update, except you wrapped the onOpenEnd
function with a new handleOpenEnd
one.
But if somehow it works for you, I'd just remove the isCloseEndAllowed.current = true;
line from your code as it is already there in my code and doesn't have to be repeated.
Still having this issue :C
Btw, I have found a tricky solution to this error.
import React, { forwardRef, useImperativeHandle, useRef } from "react";
import { View, Text, TouchableHighlight } from "react-native";
import Animated, { sub } from "react-native-reanimated";
import ReanimatedBottomSheet from "reanimated-bottom-sheet";
import { Divider, useTheme } from "react-native-paper";
import PropTypes from "prop-types";
import globalStyles from "../../styles/globalStyles";
import styles from "./styles/styles";
const BottomSheet = forwardRef(
(
{
topItems = [],
bottomItems = [],
sheetHeight = 0,
initialSnap = 1,
onOpenStart,
onOpenEnd,
onCloseStart,
onCloseEnd,
},
ref
) => {
useImperativeHandle(ref, () => ({
open,
close,
}));
const { colors } = useTheme();
const bottomSheetRef = useRef(null);
const fall = useRef(new Animated.Value(1)).current;
const isCloseEndAllowed = useRef(false); // 🐛 BUG - https://github.com/osdnk/react-native-reanimated-bottom-sheet/issues/136#issuecomment-565748783
const open = () => {
bottomSheetRef.current.snapTo(0);
};
const close = () => {
bottomSheetRef.current.snapTo(1);
};
const handleOnOpenStart = () => {
isCloseEndAllowed.current = true;
onOpenStart?.();
};
const handleOnCloseEnd = () => {
if (!isCloseEndAllowed.current) return;
onCloseEnd?.();
};
const renderContent = () => {
return (
<View style={styles.contentContainer}>
<View
style={[styles.buttonsContainer, { backgroundColor: colors.white }]}
>
{topItems.map((item, index) => {
const { disabled, title, titleColor, onPress } = item;
return (
<React.Fragment key={index}>
<TouchableHighlight
disabled={disabled}
underlayColor="#EBEBEB"
onPress={onPress}
style={[
styles.button,
index === 0 && {
borderTopLeftRadius: 15,
borderTopRightRadius: 15,
},
index === topItems.length - 1 && {
borderBottomLeftRadius: 15,
borderBottomRightRadius: 15,
},
]}
>
<Text
style={[
styles.topButtonText,
{
color: !disabled
? titleColor || colors.azureRadiance
: colors.disabled,
},
]}
>
{title}
</Text>
</TouchableHighlight>
{index !== topItems.length - 1 && <Divider />}
</React.Fragment>
);
})}
</View>
<View
style={[styles.buttonsContainer, { backgroundColor: colors.white }]}
>
{bottomItems.map((item, index) => {
const { disabled, title, titleColor, onPress } = item;
return (
<React.Fragment key={index}>
<TouchableHighlight
disabled={disabled}
underlayColor="#EBEBEB"
onPress={onPress}
style={[
styles.button,
index === 0 && {
borderTopLeftRadius: 15,
borderTopRightRadius: 15,
},
index === bottomItems.length - 1 && {
borderBottomLeftRadius: 15,
borderBottomRightRadius: 15,
},
]}
>
<Text
style={[
styles.bottomButtonText,
{
color: !disabled
? titleColor || colors.azureRadiance
: colors.disabled,
},
]}
>
{title}
</Text>
</TouchableHighlight>
{index !== bottomItems.length - 1 && <Divider />}
</React.Fragment>
);
})}
</View>
</View>
);
};
/*
🐛 BUG - Re-renders break BottomSheet's events.
With the help of abstraction, I have come up with a hacky solution to the problem. This code looks
ugly and is not optimal, but being something related to a dependency, it is the only thing I can do.
https://github.com/osdnk/react-native-reanimated-bottom-sheet/issues/183
*/
return (
<View
style={[globalStyles.overlayed, styles.container]}
pointerEvents={!sheetHeight ? "none" : "box-none"} // tricky
>
<ReanimatedBottomSheet
ref={bottomSheetRef}
snapPoints={[sheetHeight, "-10%"]} // tricky
initialSnap={initialSnap}
renderContent={renderContent}
callbackNode={fall}
enabledContentTapInteraction={false}
onOpenStart={handleOnOpenStart}
onOpenEnd={onOpenEnd}
onCloseStart={onCloseStart}
onCloseEnd={handleOnCloseEnd}
/>
{/* Overlay Shadow */}
<Animated.View
pointerEvents={"box-only"}
style={[
globalStyles.overlayed,
{
opacity: sub(0.5, fall),
backgroundColor: colors.black,
},
]}
/>
</View>
);
}
);
BottomSheet.propTypes = {
topItems: PropTypes.arrayOf(
PropTypes.shape({
disabled: PropTypes.bool,
title: PropTypes.string.isRequired,
titleColor: PropTypes.string,
onPress: PropTypes.func,
})
),
bottomItems: PropTypes.arrayOf(
PropTypes.shape({
disabled: PropTypes.bool,
title: PropTypes.string.isRequired,
titleColor: PropTypes.string,
onPress: PropTypes.func,
})
),
sheetHeight: PropTypes.number,
initialSnap: PropTypes.number,
onOpenStart: PropTypes.func,
onOpenEnd: PropTypes.func,
onCloseStart: PropTypes.func,
onCloseEnd: PropTypes.func,
};
export default BottomSheet;