Reputation: 102
I am using react navigation 5. I want to redirect with Token. But the function works twice and returns null in the first. What is the reason and solution?
export default function Router(){
const [token, setToken] = useState(null);
useEffect(() => {
getToken();
}, []);
const getToken = async () => {
const token = await AsyncStorage.getItem('token');
setToken(token);
};
console.log("token:") //console
console.log(token)
return (
<NavigationContainer>
<AppStack.Navigator>
{
token=== null ?
//..
}
</AppStack.Navigator>
</NavigationContainer>
);
}
//output
token:
null
token:
eyJhbGci..
Two rounds at the beginning and showing null in the first round prevents the program from running.
Upvotes: 0
Views: 183
Reputation: 18664
In your case, the component is rendered 2 times, because of the useEffect
hook. It acts as a componentDidMount
lifecycle method and updates the state, after the async function is completed, and here the second rerender occurred.
In general, your implementation is good.
However, you can try separating/moving the authentication login (token fetching) in a separate component, something like that:
export default function Auth(props) {
const [token, setToken] = useState(null);
useEffect(() => {
getToken();
}, []);
const getToken = async () => {
const token = await AsyncStorage.getItem('token');
setToken(token);
};
return token ? props.children : '<div>Loading ...</div>'
}
export default function Router(){
return (
<NavigationContainer>
<AppStack.Navigator>
// Your Routes definition here ...
</AppStack.Navigator>
</NavigationContainer>
);
}
export default function App() {
return (
<Auth>
<Router />
</Auth>
)
}
Upvotes: 1
Reputation: 80
Setting state is async in react, that's why first time when it is running it gives null because after running everything in the script, it resolve the async call. That's why second time you are getting the token.
See the execution order:
const [token, setToken] = useState(null);
useEffect(() => { -->(2), after component mounts
getToken();
}, []);
const getToken = async () => { -->(3)
const token = await AsyncStorage.getItem('token'); -->(6)
setToken(token); -->(7)
};
console.log("token:") //console -->(4)
console.log(token) -->(5)
return ( --> this will execute first (1)
<NavigationContainer>
<AppStack.Navigator>
{
token=== null ?
//..
}
</AppStack.Navigator>
</NavigationContainer>
);
Upvotes: 0