使用React+redux-thunk+axios做CRUD时dispatch报错问题求助
问题原因与解决方案
1. useEffect内的dispatch为什么能正常运行?
你使用的是redux-thunk中间件,它的核心作用就是允许action返回函数而非普通对象。当你执行dispatch(fetchData())时,thunk中间件会识别到fetchData返回的是函数类型,会自动把store的dispatch方法作为参数传入这个函数执行,不存在所谓的双重dispatch问题,完整执行流程如下:
- 调用dispatch,传入
fetchData()的执行结果(一个接收dispatch为参数的函数) - redux-thunk拦截到这个函数类型的action,主动执行它并注入dispatch
- 函数内部执行异步请求,请求成功后调用传入的dispatch,派发普通action对象给reducer处理
2. 删除按钮报错dispatch is not a function的原因
这个错误是两个问题叠加导致的:
错误1:点击事件绑定逻辑错误
你现在的写法是onClick={deleteData(id)},会在组件渲染时直接执行deleteData(id),而非点击时触发。deleteData执行后返回的是需要接收dispatch参数的函数,你没有把这个返回的函数交给dispatch执行,thunk不会自动注入dispatch,因此函数内部调用dispatch时就会抛出未定义的错误。
错误2:deleteData的action逻辑错误
你删除请求用了axios.get方法,且成功后的dispatch type错写为types.error,会导致删除成功后不会更新deleted字段,反而触发错误状态更新。
修复步骤
第一步:修复ButtonDelete组件
在组件内获取dispatch,点击时再把deleteData的执行结果传给dispatch:
import React from 'react' import { useDispatch } from 'react-redux' import { deleteData } from '../../actions/actions' export default function ButtonDelete({ id }) { const dispatch = useDispatch() return ( <div> <button className='btn btn-danger' onClick={() => dispatch(deleteData(id))} > Delete </button> </div> ) }
第二步:修复deleteData的action逻辑
把请求方法改为符合REST规范的DELETE(json-server原生支持),同时把成功后的dispatch type改为types.delete,删除成功后可以主动拉取最新列表保证页面数据同步:
//delete data export const deleteData = (id) => { return (dispatch) => { return axios.delete(`${baseURL}${id}`) .then(response => { return response.data }) .then(data => { console.log(data) dispatch({ type: types.delete, deletedItem: data }) // 重新拉取列表更新页面 dispatch(fetchData()) }) .catch(error => dispatch( { type: types.error, msg: "Unable to delete data" })); }; };
redux-thunk异步action标准写法
// 异步action创建函数,可传入业务参数 export const 操作名 = (自定义参数) => { // 返回接收dispatch为参数的函数 return (dispatch) => { // 可选:派发请求开始的action,用来控制loading状态 dispatch({ type: '请求开始的type' }) // 执行异步请求 axios.请求方法(请求地址, 入参) .then(res => { // 请求成功,派发成功action,携带返回数据 dispatch({ type: '请求成功的type', payload: res.data }) }) .catch(err => { // 请求失败,派发失败action,携带错误信息 dispatch({ type: '请求失败的type', msg: '错误提示' }) }) } }
组件内调用时必须使用dispatch(异步action创建函数(参数))的格式,不能直接调用异步action创建函数。
内容的提问来源于stack exchange,提问作者Maykel
相关产品推荐
相关产品推荐

