首页 > 解决方案 > useContext 调用阻止后续 useState 更新

问题描述

我有一些路线的提供者包装

<Provider>
    <Route path={ROUTES.SIGNING}><SignIn /></Route>
    <PrivateRoute path={ROUTES.PRIVATE}><Private /></PrivateRoute>
</Provider>

Provider只是一个包装器userContext

import React, { useState } from 'react';
import UserContext from '../../user.context';

let defaultUser = '';    
try {
    defaultUser = JSON.parse(localStorage.getItem('profile'));
} catch {
    defaultUser = '';
}

function Provider(props) {
    const [user, setUser] = useState(defaultUser);

    return <UserContext.Provider value={{ user, setUser }}>{props.children}</UserContext.Provider>

}

export default Provider;

我的<SignIn />组件等待来自数据服务的响应,然后 1. 尝试从 userContext 更新设置器,然后尝试更新它自己的 useState 函数。它似乎永远不会执行内部 useState 函数。

function SignIn() {
    const { user, setUser } = useContext(UserContext);
    const [formStatus, setFormStatus] = useState();

async function handleSubmit(e) {
    e.preventDefault();
    const result = await signin(credentials);

    setUser({ isInternal: result.isInternal, clientId: result.clientId });
    setFormStatus((curStatus) => ({ ...curStatus, state: FORMSTATUS.COMPLETED }));
}

为什么 setStatus 似乎永远不会触发?我认为这是因为 setUser 更新了 Provider,它是比子登录页面更高级别的组件。任何帮助都会很棒

标签: reactjsreact-hooks

解决方案


你有一个竞争条件。要解决此问题,您需要指定本地状态更新应在上下文状态更新之前完成。

解决方案:

  1. 使用React 的函数形式来设置本地状态。
  2. 然后在功能集状态调用中​​调用您的上下文状态更新。

这样,您在更新上下文之前就知道本地状态已完成。


推荐阅读