-1

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

user2775042
  • 479
  • 1
  • 6
  • 19
  • Why not pass a function(to update state in the parent component itself) instead of passing the setState directy? – Ramesh Reddy Feb 10 '20 at 07:54
  • Why are you returning an array inside `setAuthData` in homepage comp? – Ramesh Reddy Feb 10 '20 at 07: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. – user2775042 Feb 10 '20 at 08:00

3 Answers3

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.

Ramesh Reddy
  • 5,616
  • 2
  • 8
  • 23
0

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>);
};
Peter Ambruzs
  • 5,742
  • 3
  • 18
  • 26
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>);

};
Jai
  • 71,335
  • 12
  • 70
  • 93