Reputation: 1661
I have a component Home that I can render in different ways depending on the state.
I am trying to set the state of Home from localStorage
/*
The AuthContext
const globalState = {
email: null,
token: null
};
*/
export default function Home() {
const [user, setUser] = useContext(AuthContext);
useEffect(() => {
const token = localStorage.getItem('token') || null;
const email = localStorage.getItem('email') || null;
setUser({email, token});
})
}
This error keeps popping up though and I don't know how to solve it
Maximum update depth exceeded. This can happen when a component calls setState inside useEffect
I tried removing the useEffect but another error popped up
Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate
I know that this error is caused by calling the setUser repeatedly.
But I am not sure how to call the setUser only once.
Upvotes: 0
Views: 570
Reputation: 191976
The useEffect()
is called whenever the item renders, and setting the state causes the component to re-render. Add an empty dependencies arrays to the useEffect
block. This will allow to block to run only on initial render.
const [user, setUser] = useContext(AuthContext);
useEffect(() => {
const token = localStorage.getItem('token') || null;
const email = localStorage.getItem('email') || null;
setUser({email, token});
}, [])
Since this should happen only once, and the useState
is a bit redundant, you can get the same result with useMemo
instead. This is a bit less idiomatic, because getting data from localStorage
is a side effect, but it's simpler in a case like this.
const user = useMemo(() => {
const token = localStorage.getItem('token') || null;
const email = localStorage.getItem('email') || null;
return { email, token };
}, [])
Upvotes: 3