Search code examples
reactjsreact-nativereact-hooksreact-contextasyncstorage

How can I use React Native AsyncStorage with React hooks?


I have set a React Context like so:

export const TokenContext = createContext({token: ''});

and I am using it to create a Provider in my App.js, where I'm trying to first retrieve the token from AsyncStorage:

const App = () => {

    const [token, setToken] = React.useState('');

    const retrieveData = async () => {
        const storedToken = await AsyncStorage.getItem('token');
        console.log(storedToken);
        setToken(storedToken);

        return;
    };

    React.useEffect(() => {
        retrieveData();
    }, []);

    return (
        <NavigationContainer>
            <TokenContext.Provider token={token}>
                <RootNav  />
            </TokenContext.Provider>
        </NavigationContainer>
    );
};

I want to consume that Context in the RootNav component being used above:

const RootNav = () => {
    const token = React.useContext(TokenContext);
    const isSignedIn = !!token;

    return (
        <Root.Navigator>
            {isSignedIn ? (
                <>
                    <Root.Screen name={RouteNames.TAB_NAV} component={TabNav} />
                </>
            ) : (
                <>
                    <Root.Screen
                        name={RouteNames.LOGIN_SCREEN}
                        component={LoginScreen}
                    />
                </>
            )}
        </Root.Navigator>
    );
};

However, the token value in the context is undefined even though there is a value in the storage. If I manually pass the prop down to RootNav (without context), I can use it just fine, like so:

App.js

...
  return (
        <NavigationContainer>
             <RootNav token={token} />
        </NavigationContainer>
    );

RootNav.js


const RootNav = ({token}) => {
    const isSignedIn = !!token;

    return (
    ...

However, I want to use this token in places that are more nested down so I'd rather just use context if I can get it to work. Any ideas?


Solution

  • Pass token with value

        <NavigationContainer>
            <TokenContext.Provider value={{token}}>
                <RootNav  />
            </TokenContext.Provider>
        </NavigationContainer>
    

    in consumer

    const {token} = React.useContext(TokenContext);