REDUX Toolkit 中的状态问题 - 状态总是落后一步

问题描述 投票:0回答:1

所以我已经使用 RTK 工具包编写了登录功能的逻辑,这些是组件。在逻辑组件中,在调用句柄提交时,我总是第一次收到空错误,然后第二次调用它时,我得到实际状态。

我确实知道这是关于 JS 闭包,我应该使用 useEffect 处理 console.log,但是如果我需要根据登录调度的结果调用多个异步调度函数怎么办?我该如何为此编写代码?

例如,这样的事情:

  function handleSubmit(e) {
    e.preventDefault();
    dispatch(login(email, password));
    if (loginError) return;
    dispatch(fetchCustomerProfile(id))
    if(fetchError) return;
    dispatch(hideModal("login")
  }

这就是我的代码现在的样子:

const Login = () => {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const dispatch = useDispatch();
  const error = useSelector(getError);

  function handleSubmit(e) {
    e.preventDefault();
    dispatch(login(email, password));
    if (error) console.log("Const");
  }

  return (
    <form
      className="mt-4 flex flex-col m-[44px]"
      onSubmit={(e) => handleSubmit(e)}
    >
      <FormInput
        label="Email ID"
        name="emailID"
        type="text"
        value={email}
        setValue={setEmail}
      />
      <FormInput
        label="Password"
        name="password"
        type="password"
        value={password}
        setValue={setPassword}
        className="mt-3"
      />
      {error && <h3>Error Occuerd</h3>}
      <Button
        className="mt-6 ml-auto w-full bg-yellow-500 text-black"
        name={"Login"}
      />
    </form>
  );
};

authSlice.js

const initialState = {
  user: {},
  error: "",
  status: {},
};

const login = createAsyncThunk("auth/login", async ({ email, password }) => {
  try {
    const { payload: user } = await authAPI.login(email, password);
    return user;
  } catch (error) {
    throw new Error(error.message);
  }
});

const authSlice = createSlice({
  name: "auth",
  initialState,
  extraReducers: (builder) =>
    builder
      .addCase(login.pending, (state) => {
        state.status = "pending";
        state.error = "";
      })
      .addCase(login.fulfilled, (state, { payload }) => {
        state.status = "fullfilled";
        state.error = "";
        state.user = payload;
      })
      .addCase(login.rejected, (state, { error }) => {
        state.status = "rejected";
        state.error = error.message;
        console.log(state.error);
      }),
});

export default authSlice.reducer;

export const getError = (state) => state.auth.error;

export { login };

reactjs redux redux-toolkit
1个回答
0
投票

这个 是一个陈旧的关闭问题,因为从调用

loginError
的渲染周期中选择的
fetchError
handleSubmit
值在回调范围内关闭,并且永远不会是不同的值。

一个比较简单的解决方案是访问商店实例并按需获取当前状态值。

示例:

import { useDispatch, useSelector, useStore } from 'react-redux';

...

const store = useStore();
const loginError = useSelector(getLoginError);
const fetchError = useSelector(getFetchError);

async function handleSubmit(e) {
  e.preventDefault();
  await dispatch(login({ email, password }));
  if (getLoginError(store.getState())) return;
  await dispatch(fetchCustomerProfile(selectUser(store.getState()).id));
  if (getFetchError(store.getState())) return;
  dispatch(hideModal("login");
}

但这不是推荐的使用商店的方式。看来

login
fetchCustomerProfile
都是异步操作,因此您可以
await
它们来解析并 unwrap 结果。如果异步操作中出现错误,则会返回 Promise 拒绝,并且处理程序可以捕获并处理它。有关详细信息,请参阅处理 Thunk 结果

示例:

async function handleSubmit(e) {
  e.preventDefault();

  try {
    // log in with user credentials
    const user = await dispatch(login({ email, password })).unwrap();

    // login success, fetch customer profile
    await dispatch(fetchCustomerProfile(user.id)).unwrap();

    // fetch success, hide modal
    dispatch(hideModal("login");
  } catch(error) {
    // handle/ignore any rejected Promises or thrown errors
  } finally {
    // any final logic you want to run regardless of success/failure
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.