I have a modal that opens up when a user visits a screen depending on whether the user has the token or not. So the sequence of events goes like the following:
1) the screen listens for the user's arrival and attempts to retrieve the token from the local storage
2) if no token exists, the Context API opens two things simultaneously. First is the modal itself and second is the menu component within the modal (modal has three components within that opens one at a time: "menu", "signup", and "signin")
The problem I'm having is that the modal as well as the menu component opens up perfectly fine, but the newly opened modal is frozen and unclickable. This problem started occuring when I changed useEffect
to useLayoutEffect
in the following code:
const PleaseSignIn = props => {
const {
state: { authOpen },
authModalOpen
} = useContext(Context)
useLayoutEffect(() => {
const focusListener = props.navigation.addListener('didFocus', () => {
retrieveToken()
})
return () => {
focusListener.remove()
}
}, [])
const retrieveToken = async () => {
try {
const token = await AsyncStorage.getItem(LOGIN_TOKEN)
if(!token) {
authModalOpen()
}
} catch (err) {
throw new Error(err)
}
}
if(authOpen) {
return (
<View style={styles.container}>
<Auth screen={props.screen} navigation={props.navigation} />
</View>
)
}
return props.children
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}
})
export default withNavigationFocus(PleaseSignIn)
useEffect
does not trigger the listener on the first time the user visits the screen, but only on the second visit. However, the modal works fine once it's opened. useLayoutEffect
opens the modal on the first visit, but freezes the modal.
I'm using the React Native Modal:
import React, { useContext } from 'react'
import {
View,
Text,
StyleSheet,
Modal,
} from 'react-native'
import { Context } from '../../store/context'
import AuthMenu from './AuthMenu'
import Signup from './Signup'
import Signin from './Signin'
export default Auth = ({ screen, navigation }) => {
const {
state: { authOpen, authMenuOpen, signupOpen, signinOpen },
} = useContext(Context)
return (
<View style={styles.container}>
<Modal
animationType="slide"
transparent={false}
visible={authOpen}
onRequestClose={() => {
Alert.alert('Modal has been closed.');
}}
>
{authMenuOpen && <AuthMenu screen={screen} navigation={navigation} />}
{signupOpen && <Signup screen={screen} navigation={navigation} />}
{signinOpen && <Signin screen={screen} navigation={navigation} />}
</Modal>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
})
As mentioned above, when the listener fails to retrieve a token, the Context API turns on both authOpen
and authMenuOpen
. I don't think it's a race condition because useEffect
had no issues with it.
According to the similarly known issue, I've tried including the following, but with no luck:
useEffect(() => {
if (Platform.OS === 'ios') {
LayoutAnimation.easeInEaseOut();
}
})