React登录页需点击两次登录按钮的状态管理问题排查
解决React登录状态滞后导致需两次点击跳转的问题
问题根源
React中useState的状态更新是异步的,你在loginSubmitHandler里调用setLogin后立刻执行props.onLoginInfo(login),此时login还是更新前的旧状态值。第一次点击登录时,传给App的access仍是false,只有第二次点击时,才会传递更新后的true,因此出现跳转延迟。
解决方案
方案1:直接传递更新后的临时对象
不需要依赖useState的login状态,先构造好要更新的登录信息对象,同时用这个对象更新本地状态和传递给父组件:
修改LoginPage.tsx中的loginSubmitHandler:
const loginSubmitHandler = (event: any) => { event.preventDefault(); const username = event.currentTarget.username.value; const password = event.currentTarget.password.value; // 构造要更新的登录信息对象 const newLogin = { user: username, pass: password, access: username === "abc" && password === "123" }; setLogin(newLogin); // 直接传递新构造的对象,而非旧的login状态 props.onLoginInfo(newLogin); console.log("submit successfull"); };
方案2:用useEffect监听状态变化
如果需要依赖本地login状态的更新结果再传递给父组件,可以添加useEffect监听login的变化,当状态更新后再通知父组件:
修改LoginPage.tsx,先引入useEffect:
import React, { useState, useEffect } from "react";
然后添加useEffect:
useEffect(() => { // 仅在access状态变化时传递(避免初始加载时的不必要调用) props.onLoginInfo(login); }, [login, props.onLoginInfo]);
同时修改loginSubmitHandler,移除里面的props.onLoginInfo(login):
const loginSubmitHandler = (event: any) => { event.preventDefault(); if ( event.currentTarget.username.value === "abc" && event.currentTarget.password.value === "123" ) { setLogin({ user: event.currentTarget.username.value, pass: event.currentTarget.password.value, access: true, }); } else { setLogin({ user: event.currentTarget.username.value, pass: event.currentTarget.password.value, access: false, }); } console.log("submit successfull"); };
为什么这样有效
- 方案1通过直接使用刚构造的
newLogin对象,绕过了useState异步更新的延迟,确保传递给父组件的是最新的登录状态。 - 方案2利用
useEffect的依赖监听特性,在login状态真正更新完成后,再触发向父组件传递数据的逻辑,保证了数据的时效性。
内容的提问来源于stack exchange,提问作者Spacejungle
相关产品推荐
相关产品推荐

