Bottom Sheet doesn't close when navigating to different screen - react-native

I'm new to programming and when I navigate to the new screen and the bottom sheet doesn't close here's the picture of it. I'm using #gorhom/bottom-sheet^4.I have done some research and I know that using useFocusEffect could acheive it but i dont really know how. Can someone help me on this?
<BottomSheetModal
enablePanDownToClose={true}
ref={bottomSheetModalRef}
index={0}
snapPoints={snapPoint}
backdropComponent={renderBackdrop}
>
<View>
<TouchableWithoutFeedback
onPress={() => {
navigation.navigate("Settings");
}}
>
<Text style={styles.modalText}>Settings</Text>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback
onPress={() => {
navigation.navigate("Saved");
}}
>
<Text style={styles.modalText}>Saved</Text>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback
onPress={() => {
navigation.navigate("Delete");
}}
>
<Text style={styles.modalText}>Delete</Text>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback onPress={() => {}}>
<Text style={styles.modalText}>Log out</Text>
</TouchableWithoutFeedback>
</View>
</BottomSheetModal>

There are few ways to do it. Here are two:
Add useFocusEffect that runs when your screen with BottomSheetModal is unfocused:
useFocusEffect(
React.useCallback(() => {
return () => bottomSheetRef.current?.close()
}, [])
);
Close BottomSheetModal, whenever you are leaving your screen. In order to do that, you have to call bottomSheetModalRef.current?.close while navigating:
<TouchableWithoutFeedback
onPress={() => {
navigation.navigate("Settings");
bottomSheetModalRef.current?.close();
}}
>
<Text style={styles.modalText}>Settings</Text>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback
onPress={() => {
navigation.navigate("Saved");
bottomSheetModalRef.current?.close();
}}
>
<Text style={styles.modalText}>Saved</Text>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback
onPress={() => {
navigation.navigate("Delete");
bottomSheetModalRef.current?.close();
}}
>
<Text style={styles.modalText}>Delete</Text>
</TouchableWithoutFeedback>

If you're using React Navigation you can also automatically close any open modals whenever navigation changes like so:
import { useBottomSheetModal } from '#gorhom/bottom-sheet'
const Navigation = () => {
const { dismissAll: dismissAllModals } = useBottomSheetModal()
return <NavigationContainer
onStateChange={() =>
dismissAllModals()
}>
{...}
</NavigationContainer>
}

Related

How to hide keyboard while open the drawer

I want to hide the keyboard when I open the drawer but when I run the app it just opens the drawer without dismissing the keyboard. here is my code
useLayoutEffect(() => {
navigation.setOptions({
headerTitleAlign:'center',
headerLeft:() =>(
/*open drawer and dismiss keyboard*/
<TouchableWithoutFeedback onPress={() =>{Keyboard.dismiss;navigation.openDrawer()}}>
<View style={styles.menuIcon}>
<MaterialIcon name="menu" size={30} />
</View>
</TouchableWithoutFeedback>
),
how can I do to fix it?
dismiss is a method. You have to call it like this :
Keyboard.dismiss();
So, change you code with the following :
useLayoutEffect(() => {
navigation.setOptions({
headerTitleAlign:'center',
headerLeft:() =>(
/*open drawer and dismiss keyboard*/
<TouchableWithoutFeedback
onPress={() =>{
Keyboard.dismiss(); //Call it
navigation.openDrawer()
}}
>
<View style={styles.menuIcon}>
<MaterialIcon name="menu" size={30} />
</View>
</TouchableWithoutFeedback>
),
})
})
More detail is here

function not passed with required variable (Expo/React Native)

I am trying to let allow the button to navigate me to the Home Screen after pressing, but it seems like the function does not have the variable 'navigation', how do I pass this variable to the function? Below is my code snippet
const LoggedInPage = props => {
return (
<View style={styles.container}>
<Text style={styles.loggedin}>Welcome: {props.name}</Text>
<Image style={styles.image} source={{ uri: props.photoUrl }} />
<TouchableOpacity style={styles.button2} onPress={() => this.props.navigation.navigate('Home')}>
<Text style={styles.buttonText}>Get Started!</Text>
</TouchableOpacity>
</View>
)
}
There is no this binding in functional component; you can use useNavigation hook to get the navigation prop.
Code:
const LoggedInPage = ({ name, photoUrl }) => {
const navigation = useNavigation();
return (
<View style={styles.container}>
<Text style={styles.loggedin}>Welcome: {name}</Text>
<Image style={styles.image} source={{ uri: photoUrl }} />
<TouchableOpacity style={styles.button2} onPress={() => navigation.navigate('Home')}>
<Text style={styles.buttonText}>Get Started!</Text>
</TouchableOpacity>
</View>
)
}

navigate is not a function to moving screen

I am using React MNavigation5 for navigating to screen but I encounter an error:
navigate is not a function:
function Categories() {
const navigate = useNavigation();
function navigateToScreen() {
navigate('ApartmentSales');
}
return (
<View >
<Text style={Styles.TextCategories}>دسته بندی ها</Text>
{/* ---------------------------------------------------------------لایه کلی صفحه---------------------------------- */}
<View style={Styles.View}>
{/* --------------------------------------------------------------- لایه دکمه ها---------------------------------- */}
<Button style={Styles.Button} onPress={ () => navigateToScreen}>
<MaterialIcons name="waves" size={30} color={"#0c7656"} />
<Text style={Styles.Text}>زمین</Text>
</Button>
You need to actually call the function.
Instead of:
onPress={() => navigateToScreen}
Do:
onPress={() => navigateToScreen()}
Or:
onPress={navigateToScreen}
Do the following:
const navigation = useNavigation();
function navigateToScreen() {
navigation.navigate('ApartmentSales');
}

change color when button is pressed and deselect other options

I have 5 options that I wrapped with touchableopacity. I'd like that when one options is clicked that the color turns green. If i click another option then the previous option goes grey and the new option is green. Can someone please help me code this out? I don't want to write a bunch of IF statements. I feel its bad code and there is a faster way of getting to my goal. Don't mind the Alert function there I only had that when i initially setup the touchableopacity.
const [angryColor, setAngryColor] = useState('grey')
const [sadColor, setEmojiSad] = useState('grey')
const [neutral, setNuetral] = useState('grey')
const [happyColor, setHappyColor] = useState('grey')
const [laughColor, setLaugh] = useState('grey')
function toggleAngry(){
if (angryColor === 'grey'){
setAngryColor('green')
} else {
setAngryColor('grey')
}
}
return(
<View style={styles.screen}>
<View style={styles.container}>
<View style={styles.emojiView}>
<TouchableOpacity onPress={() => toggleAngry()}>
<FontAwesome5 name="angry" size={40} color={angryColor}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => Alert.alert('clicked')}>
<Entypo name="emoji-sad" size={40} color={sadColor}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => Alert.alert('clicked')}>
<Entypo name="emoji-neutral" size={40} color={neutral} />
</TouchableOpacity>
<TouchableOpacity onPress={() => Alert.alert('clicked')}>
<Entypo name="emoji-happy" size={40} color={happyColor}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => Alert.alert('clicked')}>
<FontAwesome5 name="laugh-beam" size={40} color={laughColor} />
</TouchableOpacity>
</View>
You can set a single variable and set the colour based on that. There is no need for multiple states. I added a callback function which can be used by the parent component to get this update.
const EmojiInput = (props) => {
const [selected, setSelected] = React.useState(0);
const onItemSelected=emoji=>{
setSelected(emoji);
if(props.callback){
props.callback(emoji);
}
};
return (
<View style={styles.emojiView}>
<TouchableOpacity onPress={() => onItemSelected(1)}>
<FontAwesome5 name="angry" size={40} color={selected==1?'red':'grey'} />
</TouchableOpacity>
<TouchableOpacity onPress={() => onItemSelected(2)}>
<Entypo name="emoji-sad" size={40} color={selected==2?'red':'grey'} />
</TouchableOpacity>
<TouchableOpacity onPress={() => onItemSelected(3)}>
<Entypo name="emoji-neutral" size={40} color={selected==3?'red':'grey'} />
</TouchableOpacity>
<TouchableOpacity onPress={() => onItemSelected(4)}>
<Entypo name="emoji-happy" size={40} color={selected==4?'red':'grey'} />
</TouchableOpacity>
<TouchableOpacity onPress={() => onItemSelected(5)}>
<FontAwesome5 name="laugh-beam" size={40} color={selected==5?'red':'grey'} />
</TouchableOpacity>
</View>
);
};

Hide and show component on pulling down the screen

I am trying to show a search bar on pulling down the screen and hiding it on scroll the view up.
Below is my react-native code:
render() {
return (
<View style={styles.container}>
<ScrollView
style={styles.scrollView}
onScroll={() => { console.log('onMomentumScrollBegin'); }}
onScrollBeginDrag={() => { console.log('onScrollBeginDrag'); }}
onScrollEndDrag={() => { console.log('onScrollEndDrag'); }}
>
<SearchBar
onChangeText={(obj) => {console.log(obj);}}
placeholder='Type Here...'
icon={{ type: 'font-awesome', name: 'search' }}
/>
<View style={styles.innerContainer}>
<Text>Hello</Text>
</View>
<View style={styles.innerContainer}>
<Text>Hello</Text>
</View>
</ScrollView>
</View>
);
}
onScroll, onScrollBeginDrag, onScrollEndDrag is not calling if there are not enough elements for scroll.
Here is screenshot of my screen:
If anyone has any idea about how to achieve it, that will be very helpful.
Thanks in advance.