React登录页异步状态更新问题:首次登录失败错误提示延迟
解决登录失败时错误信息首次不显示的问题
你遇到的核心问题是:调用dispatch(login(loginData))后,Redux的auth状态更新是异步的,当你在else分支调用handleSignInError时,auth.error还没来得及更新,导致setSignInError(true)未触发。第二次点击提交时,auth.error已经是上一次失败的状态,错误信息才会显示。
以下是几种可行的解决方法:
方案一:移除本地状态,直接基于Redux状态渲染错误(推荐)
这种方式彻底避免了状态同步问题,代码更简洁,符合Redux驱动UI的设计思路:
- 删除本地的
signInError状态和handleSignInError函数 - 修改
renderSigninError函数,直接通过auth.error判断是否展示错误
修改后的关键代码:
// 移除原有的signInError状态和handleSignInError函数 const renderSigninError = () => { const hasWrongCredentialsError = auth.error?.status === 401 && auth.error.message === Constants.Errors.WRONG_CREDENTIALS; if (hasWrongCredentialsError) { return ( <Box paddingTop={2.5}> <Alert variant="outlined" severity="error"> {Constants.Auth.FAILED_SIGN_IN} </Alert> </Box> ); } return null; // 无错误时返回null更简洁 } const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); const formData: any = new FormData(event.currentTarget); const loginData: LoginData = { email: formData.get("email"), password: formData.get("password"), } try { const res: any = await dispatch(login(loginData)); const resType: string = res.type; if (resType === "auth/login/fulfilled") { const userPayload: UserLogin = res.payload; const loginUser: UserInterface = { ... // 你的用户数据处理逻辑 } dispatch(setUser(loginUser)) navigate("/"); } else { console.log("Failed to login"); } } catch (error: any) { console.log(error.message); } }
方案二:用useEffect监听Redux状态变化
如果需要保留本地signInError状态,可以通过useEffect监听auth.error的更新,自动同步状态:
const [signInError, setSignInError] = useState<boolean>(false); // 添加监听auth.error的useEffect useEffect(() => { if (auth.error?.status === 401 && auth.error.message === Constants.Errors.WRONG_CREDENTIALS) { setSignInError(true); } else { setSignInError(false); // 登录成功或其他错误时重置状态 } }, [auth.error]); // 依赖auth.error,状态变化时触发回调 const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); const formData: any = new FormData(event.currentTarget); const loginData: LoginData = { email: formData.get("email"), password: formData.get("password"), } try { const res: any = await dispatch(login(loginData)); const resType: string = res.type; if (resType === "auth/login/fulfilled") { const userPayload: UserLogin = res.payload; const loginUser: UserInterface = { ... // 你的用户数据处理逻辑 } dispatch(setUser(loginUser)) navigate("/"); } else { console.log("Failed to login"); } } catch (error: any) { console.log(error.message); } }
方案三:直接使用dispatch返回的错误信息
如果你的login thunk在失败时会返回包含错误信息的action,可以直接从返回结果中判断,无需等待Redux状态更新:
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); const formData: any = new FormData(event.currentTarget); const loginData: LoginData = { email: formData.get("email"), password: formData.get("password"), } try { const res: any = await dispatch(login(loginData)); const resType: string = res.type; if (resType === "auth/login/fulfilled") { const userPayload: UserLogin = res.payload; const loginUser: UserInterface = { ... // 你的用户数据处理逻辑 } setSignInError(false); dispatch(setUser(loginUser)) navigate("/"); } else { console.log("Failed to login"); // 直接从返回的action中获取错误信息 if (res.error?.status === 401 && res.error.message === Constants.Errors.WRONG_CREDENTIALS) { setSignInError(true); } } } catch (error: any) { console.log(error.message); } }
内容的提问来源于stack exchange,提问作者code_learner93
相关产品推荐
相关产品推荐

