Redux-Saga:异步任务被调用两次

Redux-Saga: Async Task being called twice

我是 redux-saga 的新手,正在尝试替换我的 React 应用程序中的 redux-thunk。出于某种奇怪的原因,我的异步任务(worker)被执行了两次(但只有当内部有一个 AJAX 请求时——当有正常的副作用时不会发生,例如 console.log)。

从下面可以看出,我在 componentDidMount 中只调用了一次 getChildData。但是,我的 getChildDataAsync 生成器函数执行了两次(除非我注释掉 getChildData(这是一个返回承诺的异步请求)。该请求有效并且我看到了我的响应数据,但随后另一个请求被触发。

起初我认为这可能与位置更改有关,但这是在第一次访问 website/hard 刷新时发生的。

这是我设置 saga 的方式:

saga.js

import axios from 'axios';
import { call, put, take, cancel, takeLatest } from 'redux-saga/effects';
import { push, LOCATION_CHANGE } from 'react-router-redux';
import {
  CHILD_DATA_LOADING,
  CHILD_DATA_SUCCESS,
  CHILD_DATA_ERROR,
} from 'src/redux/actions/actionTypes';
import { getChildData } from 'src/api/search';

// Worker Saga - API Request
export function* getChildDataAsync(action) {
  const { id } = action;
  const params = { id, storageKeys, dataCategory, from };

  try {
    const response = yield call(getChildData, params);
    yield put({
      type: CHILD_DATA_SUCCESS,
      childData: response.data,
    });
  } catch (error) {
    yield put({
      type: CHILD_DATA_ERROR,
      childDataError: true,
      error,
    });
  }
}

// Watcher Saga
export function* watchGetChildData() {
  const childWatcher = yield takeLatest(CHILD_DATA_SUCCESS, getChildDataAsync);
}

// Root Saga - Generator Function
export default function* rootSaga() {
  yield [
    // Combine all watcher sagas
    watchGetChildData(),
  ];
}

store.js

// @flow
import { createStore, applyMiddleware } from 'redux';
import { routerMiddleware } from 'react-router-redux';
import createHistory from 'history/createHashHistory';
import rootReducer from 'src/redux/reducers/index';
import { createLogger } from 'redux-logger';
import createSagaMiddleware from 'redux-saga';
import rootSaga from 'src/redux/sagas/sagas';
import thunk from 'redux-thunk';

// React Router Redux
export const history = createHistory();

// Redux Saga
const sagasMiddleware = createSagaMiddleware();

// Add Redux Logging Only to DEV/TST Environments
const middleware = applyMiddleware(thunk, sagasMiddleware, routerMiddleware(history));

// Create store
const store = createStore(rootReducer, middleware);

// Run Redux-Saga Watchers
sagasMiddleware.run(rootSaga);

export default store;

childDataCreator.js

// @flow
import {
  CHILD_DATA_SUCCESS,
  CHILD_DATA_ERROR,
} from 'src/redux/actions/actionTypes';


// Description: Async Request to Get Child Data for Vendors/Sets
export function getChildData(
  id: string,
) {
  return { type: CHILD_DATA_SUCCESS, id };
}

React 组件

class DataView extends Component<Props> {
  componentDidMount() {
      const _id = '12345';
      this.props.getChildData(_id);
    }
  }

  rest of class....

我认为最初的 getChildData 调用应该触发类似 CHILD_DATA_REQUEST 的操作,这是 saga 应该关注的操作。

// Description: Async Request to Get Child Data for Vendors/Sets
export function getChildData(
  id: string,
) {
  return { type: CHILD_DATA_REQUEST, id };
}

// In your saga watcher function
const childWatcher = yield takeLatest(CHILD_DATA_REQUEST, getChildDataAsync);

一旦触发,将调用 getChildDataAsync 并在请求成功时触发 CHILD_DATA_SUCCESS,我猜这是预期的行为(考虑到常见的操作命名是有意义的)。