如何在一个 React+Redux 应用中使用 Redux-Saga 来处理异步的 API 请求

126 阅读2分钟

项目结构简述

假设我们正在构建一个用户信息的加载功能,以下是基本的项目结构:

  • actions/index.js —— 定义 actions
  • reducers/index.js —— 定义 reducers
  • sagas/index.js —— 定义 sagas
  • store.js —— 配置和创建 Redux store
  • App.js —— React 组件,触发 actions 并显示数据

1. 安装必要的包

首先,确保安装了必要的包:

npm install redux react-redux redux-saga axios

2. 定义 Actions

actions/index.js 中定义我们需要的 actions:

// Action Types
export const FETCH_USER_REQUEST = 'FETCH_USER_REQUEST';
export const FETCH_USER_SUCCESS = 'FETCH_USER_SUCCESS';
export const FETCH_USER_FAILURE = 'FETCH_USER_FAILURE';
​
// Action Creators
export const fetchUserRequest = () => ({
  type: FETCH_USER_REQUEST
});
​
export const fetchUserSuccess = (user) => ({
  type: FETCH_USER_SUCCESS,
  payload: user
});
​
export const fetchUserFailure = (error) => ({
  type: FETCH_USER_FAILURE,
  payload: error
});

3. 定义 Reducer

reducers/index.js 中定义 reducer:

import { FETCH_USER_REQUEST, FETCH_USER_SUCCESS, FETCH_USER_FAILURE } from '../actions';
​
const initialState = {
  loading: false,
  user: {},
  error: ''
};
​
const userReducer = (state = initialState, action) => {
  switch (action.type) {
    case FETCH_USER_REQUEST:
      return {
        ...state,
        loading: true
      };
    case FETCH_USER_SUCCESS:
      return {
        loading: false,
        user: action.payload,
        error: ''
      };
    case FETCH_USER_FAILURE:
      return {
        loading: false,
        user: {},
        error: action.payload
      };
    default:
      return state;
  }
};
​
export default userReducer;

4. 定义 Saga

sagas/index.js 中定义 saga 来处理异步逻辑:

import { call, put, takeEvery } from 'redux-saga/effects';
import axios from 'axios';
import { FETCH_USER_REQUEST, fetchUserSuccess, fetchUserFailure } from '../actions';
​
function* fetchUserSaga() {
  try {
    const response = yield call(axios.get, 'https://jsonplaceholder.typicode.com/users/1');
    yield put(fetchUserSuccess(response.data));
  } catch (error) {
    yield put(fetchUserFailure(error.message));
  }
}
​
function* userSaga() {
  yield takeEvery(FETCH_USER_REQUEST, fetchUserSaga);
}
​
export default userSaga;

5. 配置 Store

store.js 中配置 Redux store 和 saga middleware:

import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import userReducer from './reducers';
import userSaga from './sagas';
​
const sagaMiddleware = createSagaMiddleware();
const store = createStore(userReducer, applyMiddleware(sagaMiddleware));
sagaMiddleware.run(userSaga);
​
export default store;

6. 使用 Redux Store 在 React 组件中

App.js 中使用 Redux store:

import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchUserRequest } from './actions';
​
function App() {
  const { user, loading, error } = useSelector(state => state);
  const dispatch = useDispatch();
​
  useEffect(() => {
    dispatch(fetchUserRequest());
  }, [dispatch]);
​
  return (
    <div>
      {loading ? <p>Loading...</p> : error ? <p>Error: {error}</p> : <div><h1>{user.name}</h1></div>}
    </div>
  );
}
​
export default App;

这个示例展示了如何在 React+Redux 应用中使用 Redux-Saga 来处理异步的 API 请求,从而加载用户数据。这种模式非常适合处理复杂的异步逻辑和多个异步请求。