所以我已经使用 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 };
这个 是 是一个陈旧的关闭问题,因为从调用
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
}
}