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
,我猜这是预期的行为(考虑到常见的操作命名是有意义的)。
我是 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
,我猜这是预期的行为(考虑到常见的操作命名是有意义的)。