React中如何使用useReducer hook处理异步数据并更新状态?
方案思路
React 原生的 useReducer 本身仅支持同步 dispatch,不需要引入额外第三方库,只要把异步请求的不同阶段拆解成普通的 action 交给原有 reducer 处理,就能实现二者的结合,非常适合小型项目使用。
具体实现步骤
- 第一步:统一状态结构
在你的reducer.js中把异步请求相关的状态(加载态、报错信息、接口返回数据)和原有同步业务状态合并到同一个初始 state 中,不需要拆分两个独立的 reducer:
const initialState = { // 原有同步业务状态 filterLetter: '', // 新增异步请求专属状态 cocktails: [], fetchLoading: false, fetchError: null }
- 第二步:合并reducer的action处理逻辑
把同步操作、异步请求三个阶段的action全部放到同一个reducer的switch分支中处理:
function rootReducer(state, action) { switch(action.type) { // 原有同步状态处理逻辑 case 'SET_FILTER_LETTER': return {...state, filterLetter: action.payload} // 异步请求三个阶段的处理逻辑 case 'FETCH_START': return {...state, fetchLoading: true, fetchError: null} case 'FETCH_SUCCESS': return {...state, fetchLoading: false, cocktails: action.payload} case 'FETCH_ERROR': return {...state, fetchLoading: false, fetchError: action.payload} default: return state } }
- 第三步:封装异步请求函数,接收dispatch作为入参
把接口请求的逻辑单独封装,需要调用时直接把dispatch传入即可,不管是父组件还是子组件拿到dispatch都可以直接触发请求:
// 可以单独抽离到api.js文件,也可以直接写在组件逻辑中 const fetchCocktailsByLetter = async (dispatch, letter) => { // 先触发请求开始的action dispatch({type: 'FETCH_START'}) try { const res = await fetch(`你的接口请求地址/${letter}`) const data = await res.json() // 请求成功触发更新数据的action dispatch({type: 'FETCH_SUCCESS', payload: data.drinks}) } catch (err) { // 请求失败触发报错的action dispatch({type: 'FETCH_ERROR', payload: err.message}) } }
- 第四步:按需求传递dispatch调用即可
在App组件中初始化useReducer之后,直接把dispatch作为props传递给子组件:
// App.js 示例 function App() { const [state, dispatch] = useReducer(rootReducer, initialState) // 直接把dispatch当props传给Letters组件 return <Letters dispatch={dispatch} filterLetter={state.filterLetter} /> }
子组件中可以同时触发同步action和异步请求:
// letters.jsx 示例 function Letters({dispatch}) { const handleLetterClick = (letter) => { // 先触发同步action更新选中的字母 dispatch({type: 'SET_FILTER_LETTER', payload: letter}) // 再触发异步请求拉取对应数据 fetchCocktailsByLetter(dispatch, letter) } // 其余渲染逻辑省略 }
适配你的项目的优化点
- 你之前拆分的普通reducer和asyncReducer可以直接合并成上面的rootReducer,每个action对应独立的分支,逻辑不会混乱
- 不需要引入thunk之类的中间件,这种封装方式足够轻量,完全满足小型项目的需求
- 只要dispatch的传递层级不超过3层,props传递的维护成本比useContext更低,完全不需要引入context
内容的提问来源于stack exchange,提问作者robert theboss
相关产品推荐
相关产品推荐

