Bug between navigation screens and modal - react-native

So my problem is kind of weird,when i navigate between screens it seems to let the modal open but invisible.Lets say that i have a modal on my home page and pressing the menu button it opens the modal and i start navigate ,when i press the button again to open the modal and navigate to another screen it navigates but it lets open an invisible modal.
Anyone knows what kind of bug this is?
Code below :
export default function Header() {
//Use of navigation Hook
const navigation = useNavigation();
//Modal Constructor
const [modalVisible,setModalVisible] = useState(false);
return (
// Container
<View style = {styles.Header}>
{/* Modal */}
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
setModalVisible(!modalVisible);
}}>
<View style = {styles.modalStyle}>
{/* Pressable and Text for each functionality */}
<Pressable style = {styles.pressable} onPress = { () => navigation.navigate('Home')}>
<Text style = {styles. textInsideModalPressables}>Home</Text>
</Pressable>
<Pressable style = {styles.pressable} onPress = { () => navigation.navigate('Profile')}>
<Text style = {styles. textInsideModalPressables}>Profile</Text>
</Pressable>
<Pressable style = {styles.pressable} onPress = { () => navigation.navigate('Settings')}>
<Text style = {styles. textInsideModalPressables}>Settings</Text>
</Pressable>
<Pressable style = {styles.pressable} onPress = { () => navigation.navigate('LogInPage')}>
<Text style = {styles. textInsideModalPressables}>Log Out</Text>
</Pressable>
<Pressable onPress={ () => {setModalVisible(!modalVisible)}} style = {styles.pressable}>
<Text style = {styles. textInsideModalPressables}>Close modal</Text>
</Pressable>
</View>
</Modal>
{/* Pressable Mechanism in order to open the Modal */}
<Pressable onPress={ () => {setModalVisible(!modalVisible)}} style = {styles.pressableMenu}>
<SimpleLineIcons style = {styles.iconMenu} name="menu" size={Dimensions.get('window').width > 800 ? 40 : 24 } color="white" />
<Text style = {styles.menuText}>Menu</Text>
</Pressable>
<Text style = {styles.nameText}> E-Library</Text>
</View>

Related

React Native Open Modal from another Modal

Hi I am new to React Native.
I want to open a modal from another modal.
I have a modal showing event details and user can delete this event. When they press delete button, I want to add another modal saying 'are you sure ?' as in the picture
[![enter image description here][1]][1]
My code doesn't work. I used onModalHide with setTimeOut to close the first one and opend the second one. But did not work. What can be the error here ?
import React, {useRef, useState} from 'react';
import {View, ScrollView, Text, Pressable} from 'react-native';
import styles from '#/screens/dashboard/events/CreatedEventDetails.styles';
import Modal from 'react-native-modal';
import common from '#/config/common';
import {useDispatch, useSelector} from 'react-redux';
import FastImage from 'react-native-fast-image';
import images from '#/config/images';
import {Icon, LoadingIndicator} from '#/components';
import {
closeEventDetailsModal,
fetchEventsList,
handleDeleteEvent,
handleWithDrawEvent,
LOADING,
} from '#/store/events/events';
import {EVENT_STATUS} from '#/constants/eventStatus';
import {strings} from '#/localization';
import moment from 'moment';
const CreatedEventDetails = ({isVisible, closeModal}) => {
const createdEventDetails = useSelector(state => state?.events?.eventDetails);
const userInfo = useSelector(state => state.profile.user);
const dispatch = useDispatch();
const currentEventId = useSelector(state => state.events.currentEventId);
const isLoading =
useSelector(state => state?.events?.eventResponseStatus) === LOADING;
const capitilizedLetter = createdEventDetails?.name
?.toLowerCase()
.charAt(0)
.toUpperCase();
const restOfTheName = createdEventDetails?.name?.slice(1);
const deleteEvent = id => {
dispatch(handleDeleteEvent(id));
dispatch(closeEventDetailsModal());
};
const withDrawEvent = id => {
dispatch(handleWithDrawEvent(id));
dispatch(closeEventDetailsModal());
};
function getBgColor(condition) {
switch (condition) {
case EVENT_STATUS.STATUS_NEW:
return '#ef9d50';
case EVENT_STATUS.STATUS_ACCEPTED:
return '#a1dc6a';
case EVENT_STATUS.STATUS_TENTATIVE:
return 'blue';
case EVENT_STATUS.STATUS_REJECTED:
return 'red';
default:
return '#ef9d50';
}
}
// to change the modal action according to created events or accepted events, we have to check
// if the logged in user id is matching with event owner id. ( delete - withdraw action )
const isOwner = createdEventDetails?.owner?.id === userInfo?.id;
const createdEventDate = createdEventDetails?.event_date;
const formattedDate = moment(createdEventDate).format('DD MMM, ddd');
const fromTime = createdEventDetails?.from_time?.toString();
const formattedFromTime = moment(fromTime, 'hh:mm').format('LT');
const toTime = createdEventDetails?.to_time?.toString();
const formattedToTime = moment(toTime, 'hh:mm').format('LT');
// second modal state
const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false);
// second modal function
const toggleModal = () => {
// when the second modal is open, I close the first one here.
dispatch(closeEventDetailsModal());
setIsDeleteModalVisible(!isDeleteModalVisible);
};
return (
<>
<View style={styles.modalContainer}>
<Modal
isVisible={isVisible}
propagateSwipe
onBackdropPress={() => this.setState(isVisible)}
onModalHide={() => {
setTimeout(() => {
setIsDeleteModalVisible(!isDeleteModalVisible);
}, 100);
}}
onModalWillHide={() => {
setTimeout(() => {
dispatch(fetchEventsList());
}, 500);
}}>
<View style={styles.content}>
{/* we have to check if event id is matching with currentEventId to prevent undefined problem
and also modal detail can have previous event detail. this will prevent the issue */}
{createdEventDetails.id !== currentEventId ? (
<LoadingIndicator visible />
) : (
<View>
<LoadingIndicator visible={isLoading} />
<View style={styles.closeBtnContainer}>
<Pressable style={styles.closeBtn} onPress={closeModal}>
<Text style={styles.closeText}>X</Text>
</Pressable>
</View>
<View>
<Text
style={
styles.contentTitle
}>{`${capitilizedLetter}${restOfTheName}`}</Text>
<Text style={styles.contenSubtTitle}>
{formattedDate}
{'\n'}
{formattedFromTime} - {formattedToTime}
</Text>
<Text style={styles.contentText}>
At {createdEventDetails?.location}
</Text>
<View style={styles.participantsContainer}>
<Text style={styles.contentTitle}>
{strings.eventDetails.participantsTitle} (
{createdEventDetails?.invites?.length})
</Text>
<View style={common.stickyButtonLine} />
<ScrollView>
{createdEventDetails?.invites?.map(invite => (
<View style={styles.checkboxContainer} key={invite.id}>
<View style={styles.imageContainer}>
{invite?.user?.thumb ? (
<FastImage
source={{uri: invite?.user?.thumb}}
style={styles.listItemUserImage}
resizeMode={FastImage.resizeMode.cover}
/>
) : (
<Icon
icon={images.ic_user}
style={styles.noUserIcon}
/>
)}
<Text style={styles.contentPersonName}>
{invite?.user?.name}
</Text>
</View>
<View
style={{
backgroundColor: getBgColor(invite?.status),
width: 25,
height: 25,
borderRadius: 25,
}}>
<Text>{''}</Text>
</View>
</View>
))}
</ScrollView>
</View>
<View>
<View>
<Text style={styles.contentTitle}>
{strings.eventDetails.hobbiesTitle} (
{createdEventDetails?.hobbies?.length})
</Text>
<View style={common.stickyButtonLine} />
<View style={styles.hobbiesContainer}>
{createdEventDetails?.hobbies?.map(hobby => (
<View style={styles.emojiContainer} key={hobby.id}>
<Text>{hobby.emoji}</Text>
</View>
))}
</View>
<View style={common.stickyButtonLine} />
</View>
<View style={[styles.buttons, styles.singleButtonAlign]}>
{isOwner ? (
<>
<Pressable
style={styles.decline}
onPress={toggleModal}
// onPress={() =>
// deleteEvent(createdEventDetails?.id)
// }
>
<Text style={styles.declineText}>
{strings.eventDetails.delete}
</Text>
</Pressable>
// second modal content here
{/* <Modal
isVisible={isDeleteModalVisible}
propagateSwipe>
<View style={styles.content}>
<Text>Hello!</Text>
<Pressable
title="Hide modal"
onPress={toggleModal}
/>
</View>
</Modal> */}
</>
) : (
<Pressable
style={styles.decline}
onPress={() =>
withDrawEvent(createdEventDetails?.id)
}>
<Text style={styles.declineText}>
{strings.eventDetails.withdraw}
</Text>
</Pressable>
)}
</View>
</View>
</View>
</View>
)}
</View>
</Modal>
</View>
// second modal content here
<View style={styles.modalContainer}>
<Modal isVisible={isDeleteModalVisible} propagateSwipe>
<View style={styles.content}>
<Text>Hello!</Text>
<Pressable title="Hide modal" onPress={toggleModal} />
</View>
</Modal>
</View>
</>
);
};;
export default CreatedEventDetails;
````
[1]: https://i.stack.imgur.com/BUMfa.png
Here are some way of debugging.
first check both the modal is showing up by passing harcoded true value for one by one.
if its working correctly, remove those timeouts and apicalls and
just check with useState only.
if all are fine then try to call
the api.

React native dialog is closing other components on button click

//Here is my code
const MyApp=()=>{
const [visible, setVisible] = useState(false);
const refRBSheet = useRef();
const showDialog = () => {
setVisible(true);
};
const handleCancel = () => {
setVisible(false);
};
const renderItem = ({item})=>{
return(
<View style={{flex:1}}>
<TouchableOpacity onPress={() =>
openBottomSheet(refRBSheet)
}>
<Text style={styles.dialogSubTitle}>{item.title}</Text>
</TouchableOpacity>
//bottomsheet
<RBSheet ref={refRBSheet}
height={600}
closeOnDragDown={true}
>
<BottomSheet data={props} />
</RBSheet>
</View>
);
}
//method to close dialog and open bottomsheet
const openBottomSheet=(bottomSheet)=>{
bottomSheet.current.open();
handleCancel()
}
return (
<View style={styles.itemContainer}>
<TouchableOpacity onPress={showDialog}>
<Icon name="plus-circle" size={25} color="#C57F62" style={{marginRight:'7%'}} />
</TouchableOpacity>
<View style={styles.dialogContainer}>
<Dialog.Container
contentStyle={{
width:'50%',
margin: 0,
paddingBottom:'7%',
paddingTop:0,
borderRadius:10,
borderColor:"#ffffff",
backgroundColor:"#ffffff",
borderWidth:3,}}
visible={visible} onBackdropPress={handleCancel}>
<FlatList
data={dialogList}
renderItem={renderItem} />
</Dialog.Container>
</View>
);
}
I have a button in my react native application when user clicks that button it has to open a dialog.Inside a dialog i have kept list and whenever user selects item from list dialog has to close and the bottomsheet has to open.
Note:
The issue is when item is selected from dialog the bottomsheet is open and suddenly it closing both dialog and bottom sheet.
Expected output:
When item is selected from list the dialog should close and the bottomsheet has to be opened

Bottom Sheet doesn't close when navigating to different screen

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>
}

Modal open and close not working properly

I have added the below reusable code to show Modal and close the Modal when clicked outside of that Modal, when I click on a button the Modal is shown and when I click outside of that Modal it gets closed till here it is working properly but again when I click on a button to open Modal, the Modal is not shown, and I can't use props on can anyone tell me any other solution and what mistake I have made in the below code.
import React, { FunctionComponent, useState } from 'react';
import { Modal, FlatList,TouchableWithoutFeedback } from 'react-native';
interface Props {
visible: boolean;
onClose: () => void;
}
const BottomSheet: FunctionComponent<Props> = (props) => {
const [showBottomSheet,setBottomSheet]=useState(true);
if(showBottomSheet){
return (
<Modal animationType={ANIMATIONS.SlideType} transparent={true} visible={props.visible}>
<TouchableWithoutFeedback onPress={()=> setBottomSheet(false)}>
<View style={Styles.opacityContainer}></View>
</TouchableWithoutFeedback>
<View style={Styles.container}>
<View style={Styles.headerContainer}>
<View style={[Styles.header, Styles.directionRow]}>
<View>
<Text style={Styles.headerText}>Add</Text>
</View>
<View style={Styles.iconContainer}>
<Icon
name={cancel}
size={18}
IconClick={props.onClose}
/>
</View>
</View>
</View>
<View style={Styles.viewContainer}>
<SafeAreaView>
<FlatList
horizontal={false}
data={props.navData}
renderItem={renderActions}
keyExtractor={(item) => item.id}
/>
</SafeAreaView>
</View>
</View>
</Modal>
);
}
return null;
};
This is the other file where I am using the above reusable component
customer.tsx
const [showBottomSheet, setShowBottomSheet] = useState(false);
const hideBottomSheet = () => {
setShowBottomSheet(false);
};
<View style={Styles.profileContainer}>
<AddButton
onButtonPress={() => {
setShowBottomSheet(true);
}}
iconObject={{
iconName: plus,
iconSize: Sizes.plusLargeSize,
}}
/>
<BottomSheet
visible={showBottomSheet}
onClose={hideBottomSheet}
/>
</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');
}