reactjs - 用于 CRUD 操作的 Redux Toolkit Slice Race Condition
问题描述
我在使用时遇到了竞争条件问题createSlice
,我认为这可能源于对它们的正确使用的误解。问题的症结在于我正在创建一个表示特定资源的 CRUD 操作的切片,并且希望通过使用单个状态标志来保持简单。在下面的人为示例中,我有一个posts
用于创建和获取帖子的切片:
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import { postAPI } from './postAPI'
const createPost = createAsyncThunk(
'posts/createPost',
async (post, thunkAPI) => {
const response = await postAPI.createPost(post)
return response.data
}
)
const fetchPosts = createAsyncThunk(
'posts/fetchPosts',
async (userId, thunkAPI) => {
const response = await postAPI.fetchPosts(userId)
return response.data
}
)
const postsSlice = createSlice({
name: 'posts',
initialState: {
posts: [],
status: 'idle'
},
reducers: {
},
extraReducers: {
//
// Fetch Posts
//
// Update the status flag to pending
[fetchPosts.pending]: (state, action) => {
state.status = 'pending'
},
// Update the list of posts
[fetchPosts.fulfilled]: (state, action) => {
state.status = 'success'
state.posts = action.payload
},
// Fetching failed, update the status to reflect this
[fetchPosts.rejected]: (state, action) => {
state.status = 'failed'
},
},
//
// Create Post
//
// Update the status flag to pending
[createPost.pending]: (state, action) => {
state.status = 'pending'
},
// Update the list of posts after the post has been successfully created,
// (the postAPI will return the created post on success)
[createPost.fulfilled]: (state, action) => {
state.status = 'success'
// Add the new post to the state array
state.posts.push(action.payload)
},
// Creation failed, update the status to reflect this
[createPost.rejected]: (state, action) => {
state.status = 'failed'
},
},
})
获取和创建本身就可以很好地工作:
我的帖子页面...
export const MyPosts = (props) => {
const { userId } = props;
const dispatch = useDispatch();
const { status, posts } = useSelector(state => state.posts);
useEffect(() => {
dispatch(fetchPosts(userId));
}, [dispatch, userId]);
if (status === 'pending') {
display loading message...
}
if (status === 'error') {
display error message...
}
return (
...
{ status === 'success' &&
<Posts {posts} = {posts}/>
}
...
);
};
创建帖子页面...
export const CreatePost = (props) => {
const { post } = props;
...
const onCreatePostButtonClicked = () => {
dispatch(createPost(post)).then(...);
};
...
return (
<Button onClick={(event) => { createPost() } }.../>
);
};
但是,问题如下:用户在“创建帖子”页面上创建帖子,导致state
对象具有status
标志success
,然后导航到“我的帖子”页面。状态标志尚未重置,因此当“我的帖子”组件呈现时,该status
标志仍设置为success
,导致Posts
返回{ status === 'success...
块中的内容,而不是加载消息。
我对该问题的最初解决方案是添加一个reset
减速器来重置state
对象useEffect
,但这会导致额外的问题并且使用起来很麻烦。
我现在的解决方案是简单地将额外的标志添加到state
,但这感觉就像一个杂物。有没有办法确保渲染新组件时state
对象的状态标志?pending
还是这种方法不正确(每个 CRUD 操作我应该有不同的切片)?我似乎无法在网上找到任何slice
同时具有实体获取和创建的示例。
解决方案
推荐阅读
- java - 将 request.getParameterMap() 转换为带有对象列表的 bean
- ios - 为什么当我从下载文件夹中删除文件时找不到构建输入文件?
- php - 当字符串包含单引号时 PHP preg_replace() 返回 null 但否则有效
- ruby-on-rails - 安装后不显示ckeditor
- azure-cosmosdb - CosmosDB 的 Gremlin - 无法在非原始类型 GraphTraversal 上创建 ValueField
- python-3.x - Facebook Messenger bot 的日期选择器 webview - 无法将字段值带回 bot 的输入字段
- php - 检查点防火墙实施后的会话交换
- java - FileReader 和 ActionListner 之间的同步问题,FileReader 在我可以给他任何勇气之前给出空指针;
- apache-spark - 从长转换为时间戳以插入数据库
- docker - 从 jwilder/nginx-proxy 提供静态文件