我现在正在学习Redux Thunk。我尝试使用Redux Toolkit
中的createAsyncThunk
来处理用户登录,但遇到了一些问题。我在这里创建了一个demo(“right@gmail.com”+ whatever password =〉success,other combination =〉reject)。
我创建了一个模态用户输入他们的电子邮件和密码使用reactstrap
。点击Login
按钮,然后你会看到的形式。
下面是我的UserSlice.js
文件:
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import { loginFeedback } from "./feedBack";
export const login = createAsyncThunk(
"user/login",
async (userInfo, { rejectWithValue }) => {
try {
const response = await loginFeedback(userInfo);
return response.data;
} catch (err) {
return rejectWithValue(err);
}
}
);
const initialState = {
isAuthenticated: false,
isLoading: false,
user: null,
error: null,
};
const userSlice = createSlice({
name: "users",
initialState,
reducers: {},
extraReducers: {
[login.pending]: (state, action) => {
state.isLoading = true;
state.isAuthenticated = false;
},
[login.fulfilled]: (state, action) => {
state.isLoading = false;
state.isAuthenticated = true;
state.user = action.payload;
},
[login.rejected]: (state, action) => {
state.isLoading = false;
state.isAuthenticated = false;
state.user = [];
state.error = action.payload.message;
},
},
});
export default userSlice.reducer;
因此,在我的LoginModal.js
文件中,当单击Login按钮时,将启动表单提交函数handleSubmit()
:
const handleSubmit = (e) => {
e.preventDefault();
dispatch(login({ email, password }))
// something else....
}
因此在UserSlice.js
中,login
函数将负责异步调用以获取数据,因为我使用了createAsyncThunk
。createAsyncThunk
将创建三个操作:pending
、fulfilled
和rejected
。我在userSlice
的extraReducers
中相应地定义了这些操作。
// userSlice.js
[login.pending]: (state, action) => {
state.isLoading = true;
state.isAuthenticated = false;
},
[login.fulfilled]: (state, action) => {
state.isLoading = false;
state.isAuthenticated = true;
state.user = action.payload;
},
[login.rejected]: (state, action) => {
state.isLoading = false;
state.isAuthenticated = false;
state.user = [];
state.error = action.payload.message;
},
因此,如果loginFeedback
成功,则isAuthenticated
状态应设置为true
,如果调用被拒绝,则状态将设置为false
,并且表单中将显示一条错误消息。
在我的LoginModal.js
中,如果用户身份验证成功,我希望关闭模态,如果失败,则显示错误消息。为了将此操作视为正常的承诺内容,我在Redux Toolkits(here)中找到了以下内容:
由createAsyncThunk生成的thunk将始终返回一个已解析的承诺,其中包含已实现的操作对象或已拒绝的操作对象(根据需要)。
调用逻辑可能希望将这些操作视为原始承诺内容。Redux Toolkit导出一个unwrapResult函数,该函数可用于提取已实现操作的有效负载,或抛出错误,或从被拒绝的操作中抛出由rejectWithValue创建的有效负载(如果可用)。
所以我把handleSubmit
函数写成:
const handleSubmit = (e) => {
e.preventDefault();
dispatch(login({ email, password }))
.then(unwrapResult)
.then(() => {
if (isAuthenticated && modal) {
setEmail("");
setPassword("");
toggle();
}
})
.catch((error) => {
setHasError(true);
});
};
我们首先使用unwrapResult
,然后如果promise返回成功,并且状态isAuthenticated
和modal
为真,则我们使用toggle
(关闭)模态,否则我们记录错误。
但是,即使我看到Redux DevTool执行了user/login/fulfilled
操作,并且isAuthenticated
状态设置为true
,模态也不会关闭。
在我的理解中,当login
thunk完成时,isAuthenticated
应该已经被设置为true
,所以当我们调用.then()
方法时,一切都已经准备好了。所以它需要一些时间来更新自己?2所以我们不能保证React Redux在promise返回时已经更新了它?3有没有更好的方法在成功时关闭模态?
感谢您的帮助!您可以找到演示here.('right@gmail.com' +无论密码=〉成功,其他组合=〉拒绝)
1条答案
按热度按时间bq3bfh9z1#
我认为
then
回调函数中Promise
的返回值表示登录操作成功,但这并不意味着isAuthenticated
将作为true
,因为handleSubmit
将在isAuthenticated
的前一个值false
上收盘。您需要有一个自定义的
useEffect
,它在isAuthenticated
和逻辑所需的其他值上触发。以下更改应能满足您的需要:-
下面是代码和框:-