Redux连接的React组件执行DELETE/POST请求后未自动更新如何解决?
问题原因
你的问题全部来自reducer状态更新路径错误、数组操作无效,以及action没有返回Promise导致async/await失效:
- 状态更新路径和组件读取路径不一致
GET请求成功后,你直接把后端返回的完整数据赋值给了state.project,假设后端返回结构为{data: {updates: [...]}},组件读取的是props.project.data.updates,但你在ADD和DELETE的reducer分支中,把更新后的列表存在了state.project.updates,甚至DELETE分支还存到了完全不相干的members字段,组件根本读不到更新后的数据。 - DELETE分支的数组过滤操作完全无效
filter方法会返回新数组,不会修改原数组,你写的newUpdatesArray.filter(update => update.uuid !== payload)没有把结果赋值给变量,过滤后的结果直接被丢弃,数组没有任何变化。 - async/await等待dispatch无效
你的thunk action没有返回axios请求的Promise,await props.deleteUpdate()根本等不到请求和dispatch完成,后续的打印和操作拿到的都是旧状态。
修复方案
第一步:修复action creator,返回Promise
给所有axios调用加上return,这样await才能正常等待请求完成:
export const getProject = (slug) => dispatch => { // 加return return axios.get(`${backend}/api/projects/` + slug, config) .then(res => { dispatch({ type: GET_PROJECT_SUCCESS, payload: res.data, }); }).catch(err => console.log(err)); } export const postProjectUpdate = (slug, updateData) => dispatch => { // 加return return axios.post(`${backend}/api/projects/`+slug+ `/updates`,updateData, config) .then(res => { dispatch({ type: ADD_PROJECT_UPDATE_SUCCESS, payload: res.data, }); }).catch(err => console.log(err)); } export const deleteUpdate = (slug, updateID) => dispatch => { // 加return return axios.delete(`${backend}/api/projects/`+ slug + `/updates/`+ updateID, config) .then(res => { dispatch({ type: DELETE_PROJECT_UPDATE_SUCCESS, payload: updateID, }); }).catch(err => console.log(err)); }
第二步:修复reducer的状态更新逻辑
export default function ProjectReducer(state = initialState, action) { const { type, payload } = action; switch (type) { case GET_PROJECT_SUCCESS: return { ...state, project: payload }; case ADD_PROJECT_UPDATE_SUCCESS: return { ...state, project: { ...state.project, // 把updates更新到正确的data路径下 data: { ...state.project.data, updates: [...state.project.data.updates, payload.data] } } }; case DELETE_PROJECT_UPDATE_SUCCESS: // 直接过滤得到新数组,更新到正确的路径 const newUpdatesArray = state.project.data.updates.filter(update => update.uuid !== payload) return { ...state, project: { ...state.project, data: { ...state.project.data, // 更新到updates字段,不是members updates: newUpdatesArray } } }; default: return state; } }
第三步:删除组件中多余的GET请求调用
现在reducer已经能正确更新状态,不需要再手动调用getProject同步数据:
const handleProjectUpdate = async (updateInfo) => { await props.postProjectUpdate(projectID, updateInfo) // 删掉多余的props.getProject调用 } const handleDeleteUpdate = async (updateID) => { await props.deleteUpdate(projectID, updateID); // 删掉多余的props.getProject调用 };
补充说明
你之前在dispatch后立即打印props.project.data.updates拿到的是旧值,是因为组件props更新是异步的,需要等到下一次渲染才能拿到最新值,在组件顶层打印日志就能看到状态的变化。
内容的提问来源于stack exchange,提问作者Hang Ngo
相关产品推荐
相关产品推荐

