reactjs - 如何重用 Redux Toolkit createSlice 函数中的 reducer 逻辑?
问题描述
我是 React 新手,我正在学习使用 React 来构建 Web 应用程序。我发现 Redux Toolkit 很有用,并使用它的createSlice()
功能来实现基本功能。但是,我遇到了一个与“最佳实践”相关的问题,我不确定我是否正确构建了应用程序的架构。
假设我有一个user
存储在 Redux 中的对象。我创建了一个异步 thunk 函数来获取相关信息:
export const getUserInfo = createAsyncThunk('user/get', async (userId, thunkApi) => {
// fetching information using api
}
相应地,我处理pending/fulfilled/rejected
回调如下:
const userSlice = createSlice({
name: 'user',
initialState,
reducers: {
setShowProgress(state, action: PayloadAction<boolean>) {
state.showProgress = action.payload;
},
clearError(state) {
state.error = null;
state.errorMessage = null;
}
},
extraReducers: builder => {
builder.addCase(getUserInfo.pending, (state, action) => {
// My question is here >_<
}
builder.addCase(getUserInfo.fulfilled, (state, action) => {
// handle data assignments
})
builder.addCase(getUserInfo.rejected, (state, action) => {
// handle error messages
})
}
})
考虑到修改显示状态标志在其他功能 api 实现中很常见,我将两个函数 (setShowProgress()
和clearError()
) 包装在reducers
. 我的问题来了:如何在函数中引用这两个getUserInfo.pending
函数?
虽然我可以只分配showProgress
和error
状态变量getUserInfo.pending
而不是尝试调用 reducer 函数,但当我将来实现其他获取操作时,这肯定会引入重复代码。如果这不是推荐的模式,那么这种场景的最佳实践是什么?
解决方案
如果您的目标只是基于//设置loading
布尔值或属性,则可以使用1.4 版中引入的。error
pending
fulfilled
rejected
addMatcher
这是一个非常基本的示例,它使用通用帮助器在多个切片中简化此操作。
// First, we'll just create some helpers in the event you do this in other slices. I'd export these from a util.
const hasPrefix = (action: AnyAction, prefix: string) =>
action.type.startsWith(prefix);
const isPending = (action: AnyAction) => action.type.endsWith("/pending");
const isFulfilled = (action: AnyAction) => action.type.endsWith("/fulfilled");
const isRejected = (action: AnyAction) => action.type.endsWith("/rejected");
const isPendingAction = (prefix: string) => (
action: AnyAction
): action is AnyAction => { // Note: this cast to AnyAction could also be `any` or whatever fits your case best
return hasPrefix(action, prefix) && isPending(action);
};
const isRejectedAction = (prefix: string) => (
action: AnyAction
): action is AnyAction => { // Note: this cast to AnyAction could also be `any` or whatever fits your case best - like if you had standardized errors and used `rejectWithValue`
return hasPrefix(action, prefix) && isRejected(action);
};
const isFulfilledAction = (prefix: string) => (
action: AnyAction
): action is AnyAction => {
return hasPrefix(action, prefix) && isFulfilled(action);
};
const userSlice = createSlice({
name: 'user',
initialState,
reducers: {},
extraReducers: builder => {
builder.addCase(getUserInfo.fulfilled, (state, action) => {
// handle data assignments
})
// use scoped matchers to handle generic loading / error setting behavior for async thunks this slice cares about
.addMatcher(isPendingAction("user/"), state => {
state.loading = true;
state.error = '';
})
.addMatcher(isRejectedAction("user/"), (state, action) => {
state.loading = false;
state.error = action.error; // or you could use `rejectWithValue` and pull it from the payload.
})
.addMatcher(isFulfilledAction("user/"), state => {
state.loading = false;
state.error = '';
});
}
})
推荐阅读
- ios - Cordova 深层链接 - 未从通用链接中检测到查询参数
- django - 无法在同一序列化程序中获取外键表的数据
- ios - 在 SwiftUI 中将项目从一个列表拖动到另一个列表
- visual-studio-code - VSCode 多光标剪切/粘贴行为已更改
- javascript - React Native:复选框对点击没有反应
- c++ - 如何使用二叉树求解积分?
- windows - 为什么我没有在 windbg 中正确加载 ntdll,但它是下载的 windbg x86?
- python - Python回调传递默认参数
- python - Python Pandas DataFrame 返回一个月范围内的所有日期集
- java - UnreachableBrowserException - 在 OrangePiOne (Ubuntu 18.04.2) 上使用带有 java 的 PhantomJS 时