Async thunk执行成功后Redux状态未更新问题排查与解决
Redux更新数组元素状态不生效问题及解决方案
问题描述
尝试修改Redux状态中的某个元素,但始终无法生效,相关代码如下(已省略不必要部分):
postSlice代码
const INITIAL_STATE = { posts: [], error: '', }; ... builder.addCase(commentPostAsync.fulfilled, (state, action) => { const updatedPost = action.payload; state = { ...state, posts: state.posts.map((post) => { // console.log(post._id); return post._id === updatedPost._id ? { ...post, updatedPost } : post; }), }; });
问题现象
后端运行正常,刷新页面后新评论会正常展示在对应帖子中。action.payload携带了后端更新后包含新评论的帖子完整数据,map函数的匹配逻辑也正常,将日志打印放在判断条件内仅会输出匹配的post_id。但{ ...post, updatedPost }没有成功更新状态,无法定位到问题原因。
Feed.jsx组件代码
const Feed = () => { const { user } = useSelector((state) => state.auth.user); const { posts } = useSelector((state) => state.post); const dispatch = useDispatch(); useEffect(() => { dispatch(getTimeLineAsync(user._id)); }, [dispatch]); return ( <StyledFeed className='feed'> <div className='feed__container'> <Share /> {posts && posts?.map((post) => { return <Post post={post} key={post._id} />; })} </div> </StyledFeed> ); }; export default Feed;
Post.jsx组件相关代码
{isOpenComments && ( <div className='comments__container'> <div className='old-comments__container'> {post && post.comments.map((comment) => { return <Comment comment={comment} key={comment._id} />; })} </div> <div className='add-comments__container'> <div className='add-comments__avatar'> {user && <img className='user__avatar' src={user.avatar} alt='' />} </div> <form className='add-comments__input'> <input className='input' type='text' placeholder='Write a comment...' onChange={handleInputChange} name='text' /> <button className='icon' type='submit' onClick={sendComment}> <SendIcon /> </button> </form> </div> </div> )}
补充信息
console.log(updatedPost)的输出结果如下:
{ comments: (18) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}] createdAt: "2021-11-25T19:24:40.196Z" description: "test last " image: "https://travelprnews.com/wp-content/uploads/2021/11/https___specials-images.forbesimg.com_imageserve_920377840_0x0.jpg" likes: [] totalComments: 21 updatedAt: "2021-11-27T08:42:17.264Z" userId: "619a1cc54ac9c7217520e150" __v: 0 _id: "619fe2f80481f8a4edd791f4" }
问题原因
代码存在两处核心问题:
- Redux Toolkit的reducer中,直接对
state参数本身重新赋值(state = { ... })不会触发状态更新。Redux Toolkit仅允许直接修改state的属性,或者返回一个新的状态对象,不能直接给state参数整体赋值。 { ...post, updatedPost }的写法逻辑错误,这会在post对象下新增一个名为updatedPost的属性,而非将updatedPost的属性合并到post对象中,正确的合并写法应该是{ ...post, ...updatedPost },不过由于updatedPost已经是完整的帖子数据,直接替换数组对应位置的元素即可。
解决方案
修改后的reducer代码如下:
builder.addCase(commentPostAsync.fulfilled, (state, action) => { const updatedPost = action.payload; const index = state.posts.findIndex((post) => post._id === action.payload._id); const newArray = [...state.posts]; newArray[index] = updatedPost; return { ...state, posts: newArray, }; });
也可以用更简洁的写法,直接修改state属性:
builder.addCase(commentPostAsync.fulfilled, (state, action) => { const updatedPost = action.payload; const targetPost = state.posts.find(post => post._id === updatedPost._id); if (targetPost) { Object.assign(targetPost, updatedPost); } });
内容的提问来源于stack exchange,提问作者Oscar Sanz
相关产品推荐
相关产品推荐

