I'm new to React and modifying an existing starter app.
I'm implementing a check to see if the user is logged in, based on the existence of a token in localStorage. I modified my App.js file from this:
function App() {
let [ isLoggedIn, setLoggedIn ] = useState(false);
return (
<><Index isLoggedIn={isLoggedIn} setLoggedIn={setLoggedIn} /></>
);
to this:
function App() {
let [ isLoggedIn, setLoggedIn ] = useState(false);
const storageToken = localStorage.getItem('token');
if (storageToken) {
setLoggedIn(true);
} else {
setLoggedIn(false);
}
return [same as above]
This change results in a Uncaught Error: Too many re-renders.
error. Putting the check in Index.js works fine.
Looking into this some more (eg from this other question or this blog post), I understand that it's because you can't modify a state in the same function where you declare it with useState
because that state change causes the overall function to run again. But my question is: why? I suspect this is background info about how React works / the order in which React calls components, so any background reading on that topic would be appreciated!
CodePudding user response:
App is a functional component, which has its code run on every render. Changing state triggers a new render. By calling setLoggedIn() in the main body of the function, you’re creating an infinite loop.
The solution is to only read from localStorage when the component mounts/unmounts. This can be done with an effect.
useEffect(() => {
// code to run on component mount
const storageToken = localStorage.getItem('token');
if (storageToken) {
setLoggedIn(true);
} else {
setLoggedIn(false);
}
}, []);
CodePudding user response:
I think you should read this for understading how Reactjs actually works in these cases