如何在createAsyncThunk方法中覆写嵌套对象属性并更新树形结构
问题原因与解决方案
核心问题梳理
你现有代码存在两个核心错误:
- 递归替换逻辑错误:函数内直接对参数执行
obj = users赋值,只是修改了函数内部的局部变量指向,不会修改原树形结构的实际内容 - Redux Toolkit 异步逻辑处理错误:
createAsyncThunk只负责执行异步逻辑返回结果,具体的状态修改需要在切片的extraReducers中处理,直接在thunk里修改传入的参数不会同步到Redux store中
具体实现步骤
1. 改造createAsyncThunk逻辑
仅保留异步请求逻辑,返回需要用到的更新参数即可,不需要在thunk内修改状态:
export const fetchChildrenNews = createAsyncThunk( 'news/fetchChildrenNews', async ([item]) => { // 请求所有子项完整数据 const res = await Promise.all( item.kids.map(id => fetch(`https://hacker-news.firebaseio.com/v0/item/${id}.json?print=pretty`) ) ); const childItems = await Promise.all(res.map(r => r.json())); // 返回目标节点ID和对应的子项数组 return { targetId: item.id, childItems } } );
2. 在切片extraReducers中处理状态更新
利用RTK内置的Immer库,直接递归修改store中的news树即可,不需要手动做深拷贝:
const newsSlice = createSlice({ name: 'news', initialState: { newsTree: {}, // 这里存储你的完整news树形结构 loading: false, error: null }, reducers: {}, extraReducers: builder => { builder .addCase(fetchChildrenNews.pending, (state) => { state.loading = true; }) .addCase(fetchChildrenNews.fulfilled, (state, action) => { state.loading = false; const { targetId, childItems } = action.payload; // 递归查找对应ID的节点替换kids属性 const updateNode = (node) => { if (node.id === targetId) { node.kids = childItems; return; } // 子节点存在则递归遍历 if (node.kids?.length) { node.kids.forEach(child => updateNode(child)); } } updateNode(state.newsTree); }) .addCase(fetchChildrenNews.rejected, (state, action) => { state.loading = false; state.error = action.error.message; }) } })
提示:如果你的完整news树是数组格式存储的多个根节点,把
updateNode(state.newsTree)改成state.newsTree.forEach(root => updateNode(root))即可。
内容的提问来源于stack exchange,提问作者Lex
相关产品推荐
相关产品推荐

