如何将基于Redux-Thunk的API数据获取示例代码改写为Redux-Saga?
把Redux-Thunk的API请求示例重写为Redux-Saga
没问题!我来帮你把这段用Redux-Thunk实现的API请求代码改成Redux-Saga版本,咱们一步步拆解,保证逻辑清晰易懂。
首先,你需要先安装Redux-Saga的依赖:
npm install redux-saga axios
接下来,咱们从核心逻辑开始重构:
1. 保留原有的Reducer和Action Types
Reducer部分基本不需要改动,不过我先帮你修正一个小bug:原来的endFetchFun里的action type写错成PROCESS_FETCH了,应该改成END_FETCH,不然错误状态没法正确更新。
2. 编写Redux-Saga的核心逻辑
Redux-Saga用Generator函数来处理异步流程,我们需要两个核心函数:
- Worker Saga:负责实际执行异步请求的逻辑
- Watcher Saga:监听特定的action,一旦触发就调用对应的Worker Saga
3. 配置Saga中间件并创建Store
把原来的Thunk中间件替换成Saga中间件,然后启动Saga监听。
完整重写后的代码
import React from 'react'; import { createStore, applyMiddleware } from 'redux'; import ReactDOM from "react-dom"; import createSagaMiddleware from 'redux-saga'; // 导入saga中间件 import { takeEvery, call, put } from 'redux-saga/effects'; // saga核心API import axios from 'axios'; function App(props) { // 初始状态保持不变 const initialState = { loading: false, data: [], error: '' }; // Reducer 修正了endFetch的type错误 const reducer = function (state = initialState, action) { switch (action.type) { case 'START_FETCH': return { ...state, loading: true }; case 'PROCESS_FETCH': return { ...state, loading: false, data: action.payload, error: "" }; case 'END_FETCH': return { ...state, loading: false, data: [], error: action.payload }; default: return state; } }; // Action Types const START_FETCH = 'START_FETCH'; const PROCESS_FETCH = 'PROCESS_FETCH'; const END_FETCH = 'END_FETCH'; const FETCH_USERS_REQUEST = 'FETCH_USERS_REQUEST'; // 新增一个触发saga的action type // Action Creators const startFetchFun = () => ({ type: START_FETCH }); const processFetchFun = (users) => ({ type: PROCESS_FETCH, payload: users }); const endFetchFun = (error) => ({ type: END_FETCH, payload: error }); const fetchUsersRequest = () => ({ type: FETCH_USERS_REQUEST }); // 触发saga的action // Worker Saga: 执行异步请求逻辑 function* fetchUsersSaga() { try { yield put(startFetchFun()); // 发送开始请求的action // 用call调用异步函数,axios.get返回Promise const response = yield call(axios.get, 'https://jsonplaceholder.typicode.com/users'); yield put(processFetchFun(response.data)); // 请求成功,发送数据action } catch (error) { yield put(endFetchFun(error.message)); // 请求失败,发送错误action console.log(error.message); } } // Watcher Saga: 监听FETCH_USERS_REQUEST action,每次触发都调用fetchUsersSaga function* watchFetchUsers() { yield takeEvery(FETCH_USERS_REQUEST, fetchUsersSaga); } // 创建saga中间件并启动watcher const sagaMiddleware = createSagaMiddleware(); const store = createStore(reducer, applyMiddleware(sagaMiddleware)); sagaMiddleware.run(watchFetchUsers); // 启动saga监听 // 订阅store变化,打印状态 store.subscribe(() => { console.log(store.getState()) }); // 现在dispatch的是触发saga的action,而不是thunk函数 store.dispatch(fetchUsersRequest()); return ( <div className="main"> <h1>Redux-Saga</h1> </div> ); } ReactDOM.render( <App/>, document.getElementById('root') );
关键知识点解释
takeEvery:监听每一个FETCH_USERS_REQUESTaction,只要这个action被dispatch,就会执行对应的fetchUsersSagacall:用来调用异步函数(比如axios.get),它会等待Promise完成后再继续执行generatorput:相当于Redux里的dispatch,用来发送action给reducer更新状态- 和Thunk的区别:Thunk是把异步逻辑写在action creator里,而Saga是把异步逻辑抽离到单独的generator函数中,让action creator回归纯粹的“创建action”的职责,逻辑更清晰,也更方便处理复杂的异步流程(比如取消请求、重试等)
内容的提问来源于stack exchange,提问作者user10201522
相关产品推荐
相关产品推荐

