首页 > 解决方案 > Redux saga 在遇到减速器后无法捕捉动作

问题描述

我正在尝试为客户实现 redux saga,但在击中减速器后我无法让 saga 捕捉动作。我的传奇似乎从来没有发生过,所以在我调用“DATA_FETCH_REQUESTED”reducer 操作后,我没有得到我期望的结果。

我期望的结果是:我的 saga 触发并且我的 redux 存储中的 errorMessage 变量包含获取的数据,或者如果获取失败,则错误消息。

我得到的结果是:我的 saga 没有触发,并且我的 redux 存储中的 errorMessage 变量总是最终包含字符串“### saga failed to catch this action ###”(它应该但应该被更正通过我的传奇的行动,从未发生过)

我在这里担心的是 saga 中间件永远无法正常启动。我已经在我的传奇中添加了打印语句,但我从未在我的控制台中看到它们,这似乎证实了我的理论。任何帮助将不胜感激。请参见下面的代码:

这是我的根传奇文件:


    function fetchData() {
        // fetches data
    }

    function* callFetchData() {
        try {
            const data = yield call(fetchData)
            yield put({ type: "DATA_FETCH_SUCCEEDED", data: data })
        } catch (e) {
            yield put({ type: "DATA_FETCH_FAILED", message: e.message })
        }
    }

    function* fetchDataSaga() {
        yield* takeEvery("DATA_FETCH_REQUESTED", callFetchData)
    }

    function* rootSaga() {
        yield [fork(fetchDataSaga)]
    }

    export default rootSaga

这是我的减速机:


    const initialState = {
        errorMessage: null,
    }

    const dataReducer = (state = initialState, { payload, type }) => {
        switch (type) {
            case "DATA_FETCH_REQUESTED": {
                return {
                    ...state,
                    errorMessage: '### saga failed to catch this action ###',
                }
            }
            case "DATA_FETCH_SUCCEEDED": {
                return {
                    ...state,
                    errorMessage: payload.data,
                }
            }
            case "DATA_FETCH_FAILED": {
                return {
                    ...state,
                    errorMessage: payload.errorMessage,
                }
            }
            default: {
                return state
            }
        }
    }

    export default dataReducer

这是我的 index.js 文件:


    import React from 'react'
    import ReactDOM from 'react-dom'
    import App from './App'
    import { Provider } from 'react-redux'
    import rootReducer from './redux/rootReducer'
    import { createStore, applyMiddleware } from 'redux'
    import createSagaMiddleware from 'redux-saga'
    import rootSaga from './sagas/rootSaga'

    const sagaMiddleware = createSagaMiddleware()

    const store = createStore(rootReducer, applyMiddleware(sagaMiddleware))

    sagaMiddleware.run(rootSaga)

    ReactDOM.render(
        <Provider store={store}>
            <App />
        </Provider>,
        document.getElementById('root')
    )

更新:

看起来我只是忘记将 rootSaga 的 yield 值包装在 'redux-saga/effects' 库中的 all() 方法中。将其更改为以下内容:

    function* rootSaga() {
        yield all([fork(fetchDataSaga)])
    }

没有错误,因为这是一个逻辑问题而不是句法问题

标签: redux-saga

解决方案


在击中减速器之前,我无法让 saga 捕捉到动作。

Redux 传奇无法做到这一点。Redux saga 的设计目的是先将 action 发送到 reducer,然后再发送到 sagas。

如果您出于某种原因需要先由 saga 处理一个动作,那么我建议将其拆分为两个动作:第一个动作不会被任何减速器监听,因此即使它进入减速器也没有效果. 然后 saga 得到它,它转身并调度第二个动作。第二个动作是减速器处理的动作。


推荐阅读