0

I am using React Context to pass in the state and setState like this

const [authContext, setAuthData] = useState({
    isAuthenticated: false,
    userID:"-1",
    email:"test",
    name:"test"
  });

<AuthContext.Provider value={[authContext,setAuthData]}>
          <Router>
            <NavbarMenu />
              <div className="AllElements">
                  <Switch>
                    <Route exact path="/" component={HomePage} />
                    <Route component={Routes} />
                  </Switch>
              </div>
          </Router>
        </AuthContext.Provider> 

and in another component, I retrieve it like this

const [authContext, setAuthData ] = useContext(AuthContext);
const { isAuthenticated } = authContext;

I call setAuthData like this whenever I want to update authContext

const HomePage = () => {
if(data && data.login && data.login.token){
        console.log("Data token exists");
        setAuthData(() => [{
            isAuthenticated: true,
            userID:data.login.id,
            email:data.login.email,
            name:data.login.name
        }]);
    } 

 return (<div><p>test</p></div>);
};
export default HomePage;

However, once it hits setAuthData, everything inside the if {} gets called multiple times. I keep seeing multiple "Data token exists" in the console until it errors out to Maximum update depth exceeded

3
  • Why not pass a function(to update state in the parent component itself) instead of passing the setState directy? Commented Feb 10, 2020 at 7:54
  • Why are you returning an array inside setAuthData in homepage comp? Commented Feb 10, 2020 at 7:59
  • Because I need to reuse AuthContext in other components as well. I don't want to just pass the same function as a prop to every component that I want to reuse that in. Commented Feb 10, 2020 at 8:00

3 Answers 3

1

You get an infinite loop because setAuthData call changes authContext. When authContext changes HomePage would re-render and it trigger setAuthData again.

Make sure you call setAuthData only once for example:

const HomePage = () => {
  React.useEffect(() => {
    if (data && data.login && data.login.token) {
      console.log("Data token exists");
      setAuthData(() => [
        {
          isAuthenticated: true,
          userID: data.login.id,
          email: data.login.email,
          name: data.login.name
        }
      ]);
    }
  }, [data]);

 return (<div><p>test</p></div>);
};
Sign up to request clarification or add additional context in comments.

Comments

0

I guess you should do the state update in useEffect hook and pass the second parameter to react only when it updates:

const HomePage = () => {

    useEffect(()=>{
        //if(data && data.login && data.login.token){
            console.log("Data token exists");
            setAuthData(() => [{
                isAuthenticated: true,
                userID:data.login.id,
                email:data.login.email,
                name:data.login.name
            }]);
       // } 
     }, [data]); //<-----second param if it has any changes then run effect
     return (<div><p>test</p></div>);

};

Comments

0

This might be the issue:

const HomePage = () => {
if(data && data.login && data.login.token){
        console.log("Data token exists");
        setAuthData(() => [{
            isAuthenticated: true,
            userID:data.login.id,
            email:data.login.email,
            name:data.login.name
        }]);
    } 

 return (<div><p>test</p></div>);
};
export default HomePage;

Your updated state should be an object not an array based on the previous state in parent component so change the returned value to this:

const HomePage = () => {
if(data && data.login && data.login.token){
        console.log("Data token exists");
        setAuthData(() => ({
            isAuthenticated: true,
            userID:data.login.id,
            email:data.login.email,
            name:data.login.name
        }));
    } 

 return (<div><p>test</p></div>);
};
export default HomePage;

As described in peter's answer you should also use the useEffect hook to stop the update cycle.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.