4

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();
      }
  })
Kevvv
  • 3,655
  • 10
  • 44
  • 90

0 Answers0