redux 为什么派遣工作有延迟?

qzwqbdag  于 2023-03-08  发布在  其他
关注(0)|答案(1)|浏览(147)

我有一个简单的代码:

const Login = (): JSX.Element => {
  const {errors}= useAppSelector(state => state.errorsReducer)
  const dispatch = useAppDispatch();

  const navigate = useNavigate();
  
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')

  const onSubmit = (e: FormEvent) => {
    e.preventDefault();
  };

  const login = () => {
    dispatch(errorsSlice.actions.clearErrors());
    console.log(errors);
    const userData = {
      email: email,
      password: password
    }
    
    if(!userData.email || !userData.password){
      dispatch(errorsSlice.actions.addError('Email or password is undefined'));
    }

    if(errors.length === 0){
      axios
        .post('http://localhost:7000/auth/login', userData)
        .then(response =>{
          const decodedToken: IUser = jwt_decode(response.data.token);
          localStorage.setItem('userData', JSON.stringify(decodedToken));
          localStorage.setItem('token', JSON.stringify(response.data.token));
          navigate('/')
        })
        .catch(e => {
          const errorMessage = e?.response?.data?.message
          dispatch(errorsSlice.actions.addError(errorMessage));
        });
    }
    console.log(errors);
  }

    return (
      <main className="form-signin m-auto"  style={{height: 600}}>
        <div className='container h-100 d-flex align-items-center justify-content-center'>
          <form onSubmit={(e) => onSubmit(e)} style={{width: 400}}>
            <h1 className="h3 mb-3 fw-normal">Auth</h1>

            <div className="form-floating">
              <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} className="form-control" id="floatingInput" placeholder="name@example.com"/>
              <label htmlFor="floatingInput">Email</label>
            </div>
            <div className="mt-2 form-floating">
              <input type="password" className="form-control" value={password} onChange={(e) => setPassword(e.target.value)} id="floatingPassword" placeholder="Password"/>
              <label htmlFor="floatingPassword">Password</label>
            </div>

            <div className="checkbox mt-2 mb-3">
              <label>
                Or <Link to='/registration'>click that</Link> to registration. 
              </label>
            </div>
            <button className="w-100 btn btn-lg btn-primary" onClick={() => login()} type="submit">Login</button>
          </form>
        </div>

        <>
          {errors.map((error) => {
              return <MyToast
                text = {error}
                color = {'bg-danger'}
                show = {true}
                key = {error}
              />
            })}
          </>
        
    </main>
    )
}

点击登录按钮调用函数登录()在没有错误的情况下发送服务器上的请求。我测试有错误的请求。这在第一次工作,调度设置错误存储和所有工作良好,但在第二次点击应工作调度(errorsSlice.actions.clearErrors()),但是他的工作有延迟,并且当我的函数转到表达式if时(errors.length === 0),那么表达式返回false,因为errors.length = 1,尽管分派(errorsSlice.actions.clearErrors())应该已经工作了。我需要做什么,使代码工作真?

5cnsuln7

5cnsuln71#

选定的errors状态值已在login回调作用域中关闭,它将***永远不会***成为回调中的其他值。您不能调度操作以更新状态并期望关闭的值更改。
我怀疑您实际上只是想验证输入并在出现问题时分派addError操作,否则继续登录流程。我建议进行一个小的重构来计算和检查本地错误,以避免所选errors状态上的过时闭包问题。
示例:

const Login = (): JSX.Element => {
  const { errors } = useAppSelector(state => state.errorsReducer)
  const dispatch = useAppDispatch();

  const navigate = useNavigate();
  
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')

  const onSubmit = async (e: FormEvent) => {
    e.preventDefault();
  
    dispatch(errorsSlice.actions.clearErrors());
    
    // check for field data issue, early return
    if (!email || !password){
      dispatch(errorsSlice.actions.addError('Email or password is undefined'));
      return;
    }

    // no field data issues, try authenticating
    try {
      const userData = { email, password };
      const response = await axios.post(
        "http://localhost:7000/auth/login",
        userData
      );

      const decodedToken: IUser = jwt_decode(response.data.token);
      localStorage.setItem('userData', JSON.stringify(decodedToken));
      localStorage.setItem('token', JSON.stringify(response.data.token));
      navigate('/');
    } catch(e) {
      const errorMessage = e?.response?.data?.message
      dispatch(errorsSlice.actions.addError(errorMessage));
    };
  }

  return (
    <main className="form-signin m-auto"  style={{ height: 600 }}>
      <div className="container h-100 d-flex align-items-center justify-content-center">
        <form onSubmit={onSubmit} style={{width: 400}}>
          <h1 className="h3 mb-3 fw-normal">Auth</h1>

          <div className="form-floating">
            <input
              type="email"
              value={email}
              onChange={(e) => setEmail(e.target.value)}
              className="form-control"
              id="floatingInput"
              placeholder="name@example.com"
            />
            <label htmlFor="floatingInput">Email</label>
          </div>
          <div className="mt-2 form-floating">
            <input
              type="password"
              className="form-control"
              value={password}
              onChange={(e) => setPassword(e.target.value)}
              id="floatingPassword"
              placeholder="Password"
            />
            <label htmlFor="floatingPassword">Password</label>
          </div>

          <div className="checkbox mt-2 mb-3">
            <label>
              Or <Link to='/registration'>click that</Link> to registration. 
            </label>
          </div>
          <button className="w-100 btn btn-lg btn-primary" type="submit">
            Login
          </button>
        </form>
      </div>
      <>
        {errors.map((error) => (
          <MyToast
            key={error}
            color="bg-danger"
            show
            text={error}
          />
        ))}
      </>
    </main>
  )
}

相关问题