React ContextAPI变量首次点击无法获取最新值问题求解
问题原因
- 登录按钮的点击回调中没有调用
signIn异步方法,首次点击时未触发接口请求,Context中的count状态还是初始的undefined,判断count > 1自然不成立。 - React的状态更新是异步的,
setCount执行后不会立刻修改当前闭包内的count值,只有等组件重新渲染后才能拿到更新后的状态。就算你在点击回调中调用了signIn,同一个回调内立刻读取count拿到的还是更新前的旧值,所以第一次点击判断不生效,第二次点击时count已经完成更新,才能拿到正确值。 - 原有逻辑错误:点击回调中不管
count判断结果如何,都会直接执行Router.push("/dashboard"),会导致选择企业的逻辑还没执行就跳转页面。
解决方法
方案1:直接使用接口返回值判断(推荐)
不需要依赖状态判断,直接在signIn方法中返回接口拿到的企业数量,点击回调中await调用后直接用返回值处理逻辑:
修改AuthContext.ts中的signIn方法
async function signIn({ cpf, password, empresa }: SignInCredentials) { // 修正原笔误:password赋值错写为cpf setUser({ cpf: cpf, password: password }) if (!empresa) { const response: ResponseProps = await api.post('/session', { LOGIN: cpf, SENHA: password }) const empresas = response.data.payload; setEmpresas(empresas); setCount(empresas.length) // 返回企业数量给调用方 return empresas.length } if (empresa) { const response: ResponseUserProps = await api.post('/session', { LOGIN: cpf, SENHA: password, EMPRESA: empresa }) const { token } = response.data.payload; setCookie(undefined, '@allNube.token', token, { maxAge: 60 * 60 * 24, // 24小时 }) api.defaults.headers['Authorization'] = `Bearer ${token}`; Router.push('/dashboard') return 0 } }
修改登录组件逻辑
export function Login() { const { signIn, empresas } = useContext(AuthContext); // 假设你已经在组件内维护了表单的cpf、password状态 const [cpf, setCpf] = useState('') const [password, setPassword] = useState('') return ( <Button onClick={async () => { // 先调用登录接口获取企业数量 const companyCount = await signIn({cpf, password}) if (companyCount > 1) { onSelectCompanyDrawer(); } else if(companyCount === 1) { // 只有1家企业时直接调用登录完成跳转 await signIn({cpf, password, empresa: empresas[0].CODIGO}) } }} w="200px" h="48px" mb="4" type="submit" > Acessar </Button> ); }
方案2:用useEffect监听count变化
如果需要依赖Context的count状态做逻辑,可以通过useEffect监听count变化,状态更新后自动触发对应逻辑:
export function Login() { const { signIn, count, empresas } = useContext(AuthContext); const [cpf, setCpf] = useState('') const [password, setPassword] = useState('') // count更新后自动执行判断 useEffect(() => { if(!count) return if(count > 1) { onSelectCompanyDrawer(); } else if(count === 1) { signIn({cpf, password, empresa: empresas[0].CODIGO}) } }, [count, cpf, password, empresas, signIn]) return ( <Button onClick={() => signIn({cpf, password})} w="200px" h="48px" mb="4" type="submit" > Acessar </Button> ); }
内容的提问来源于stack exchange,提问作者Jaymes Costa
相关产品推荐
相关产品推荐

