Redux-Saga
redux-saga 是一个用于管理应用程序副作用 (例如异步获取数据, 访问浏览器缓存等) 的 JavaScript 库, 它的目标是让副作用管理更容易, 执行更高效, 测试更简单, 处理故障更容易.
redux-saga 相当于一个放置在 action 与 reducer 中的垫片.
之所以称之谓副作用呢, 就是为了不让触发一个 action 时, 立即执行 reducer. 也就是在 action 与 reducer 之间做一个事情, 比如异步获取数据等.
redux-saga 使用了 ES6 中的 Generator 功能, 避免了像 redux-thunk 的回调地狱.
如何使用
安装
- $ NPM install --save redux-saga
- // 或者
- $ yarn add redux-saga
示例
假设有一个 UI 界面, 是根据用户 ID 显示用户详情的. 那么我们需要通过接口从数据库根据 userId 来获取数据.
简单起见, 我们在本地使用一个 JSON 文件来模拟数据库数据.
- {
- "297ee83e-4d15-4eb7-8106-e1e5e212933c": {
- "username": "Saga"
- }
- }
创建 UI Component
- import React from 'react';
- import { USER_FETCH_REQUESTED } from '../../../actions/User';
- export default class extends React.Component {
- constructor(props) {
- super(props);
- this.state = { userId: '297ee83e-4d15-4eb7-8106-e1e5e212933c' }
- }
- render() {
- const { userInfo = {}, dispatch } = this.props;
- return (
- <React.Fragment>
- <button onClick={() => {
- dispatch({ type: USER_FETCH_REQUESTED, payload: { userId: this.state.userId } });
- }}>Get User Info</button> <span > 用户名: {userInfo.username}</span>
- </React.Fragment>
- );
- }
- }
创建 saga, 这里的 saga 就相当于 action.
- import { call, put, takeEvery } from 'redux-saga/effects'
- import { fetchUserApi } from '../api/user';
- import { USER_FETCH_REQUESTED, USER_FETCH_SUCCEEDED, USER_FETCH_FAILED } from '../actions/User';
- function* fetchUser({ payload }) {
- try {
- const user = yield call(fetchUserApi, payload.userId);
- yield put({ type: USER_FETCH_SUCCEEDED, user });
- } catch (e) {
- yield put({ type: USER_FETCH_FAILED, message: e.message });
- }
- }
- const userSaga = function* () {
- yield takeEvery(USER_FETCH_REQUESTED, fetchUser);
- }
- export default userSaga;
关于 fetchUserApi, 我们会在后面的章节中描述. 这里仅获取了 JSON 文件中与 userId 相对应的数据.
把 saga 放入 store 中:
- import createSagaMiddleware from 'redux-saga';
- import Sagas from '../sagas/index';
- const sagaMiddleware = createSagaMiddleware()
- const store = createStore(
- reducer,
- applyMiddleware(sagaMiddleware)
- )
- sagaMiddleware.run(Sagas)
最后再实现相就的 reducer 即可:
- import { USER_FETCH_SUCCEEDED } from '../actions/User';
- const initialState = { user: {} };
- export default (state = initialState, action) => {
- switch (action.type) {
- case USER_FETCH_SUCCEEDED:
- return { ...state, user: action.user };
- default:
- return state;
- }
- }
来源: https://www.jb51.net/article/150669.htm