开发者问题收集

使用 React Context 时如何更新状态?

2020-02-10
701

我使用 React Context 传递状态并像这样设置状态

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> 

在另一个组件中,我像这样检索它

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

每当我想要更新 authContext 时,我都会像这样调用 setAuthData

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;

但是,一旦它命中 setAuthData,if {} 中的所有内容都会被多次调用。我不断在控制台中看到多个“数据令牌存在”,直到它错误地显示“超出最大更新深度”

3个回答

由于 setAuthData 调用会更改 authContext,因此会出现无限循环。当 authContext 更改时,HomePage 将重新呈现并再次触发 setAuthData。

请确保只调用 setAuthData 一次,例如:

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
2020-02-10

我猜你应该在 useEffect 钩子中进行状态更新,并传递第二个参数以便仅在更新时做出反应:

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
2020-02-10

这可能是问题所在:

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;

更新后的状态应该是一个对象,而不是基于父组件中先前状态的数组,因此将返回值更改为:

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;

正如 peter 的回答中所述,您还应该使用 useEffect 钩子来停止更新周期。

Ramesh Reddy
2020-02-10