redux-saga не может уловить действия, отправленные усилителями магазина

Мне нужно использовать усилитель магазина (reactReduxFirebase из react-redux-firebase) в моем redux приложение. Этот энхансер отправляет действие, оно выглядит примерно так (очень упрощенно):

const reactReduxFirebase = (next) => {
  return (reducer, initialState, middleware) => {
    const store = next(reducer, initialState, middleware);
    store.dispatch({
      type: 'DUMMY_ACTION'
    });
    return store;
  }
}

// usage
const sagaMiddleware = createSagaMiddleware();
const middleware = [sagaMiddleware];
const store = createStore(
  reducer,
  initialState,
  compose(
    applyMiddleware(...middleware),
    reactReduxFirebase
  )
);
sagaMiddleware.run(sagas);

// sagas.js
function* handle(action) {
  console.log(action);
}

function* saga() {
  yield takeEvery('*', handle);
}

export default saga;

Я хочу, чтобы saga слушала все действия и console.log их, но она не улавливает 'DUMMY_ACTION', отправляемую энхансером, потому что она отправляется до того, как saga начинает слушать (sagaMiddleware.run(sagas);). Из документов redux-saga кажется, что сага должна запускаться после applyMiddleware, поэтому я не могу запустить сагу перед усилителем. Есть ли способ заставить его работать, чтобы сага также улавливала действие усилителя?


person user1091733    schedule 31.12.2016    source источник
comment
Вы пытались изменить порядок аргументов compose. Таким образом firebase будет передана в расширенный сагой createStore, который может решить вашу проблему.   -  person TomW    schedule 02.01.2017


Ответы (2)


попробуйте это для саг

function* log(action) {
  while (true) {
    yield take('*');
    console.log(action);
  }
}

export default function* root() {
  yield all([call(log)]);
}

просто чтобы посмотреть, работает ли это, вы можете попробовать перейти на takeEvery, у меня были проблемы с этим, и создание дескрипторов, специфичных для саги, сработало

person AlexGvozden    schedule 26.02.2018

Решение на основе applyMiddlware:

import createSagaMiddleware from 'redux-saga';
import { takeEvery } from 'redux-saga/effects';
import { createStore, compose } from 'redux';
import {
  reducer
} from '../reducers';

function sagaPreinitMiddleware(saga) {
  return (createStore) => (reducer, preloadedState, enhancer) => {
    const sagaMiddleware = createSagaMiddleware();

    const store = createStore(reducer, preloadedState, enhancer);
    let dispatch = store.dispatch;
    const middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    };
    dispatch = compose(sagaMiddleware(middlewareAPI))(store.dispatch);
    sagaMiddleware.run(saga); // run the saga
    return {
      ...store,
      dispatch
    };
  };
}

const reactReduxFirebase = (next) => {
  return (reducer, initialState, middleware) => {
    const store = next(reducer, initialState, middleware);
    store.dispatch({
      type: 'DUMMY_ACTION'
    });
    setTimeout(store.dispatch({
      type: 'DUMMY_ACTION_1'
    }), 100);
    return store;
  };
};

// usage
const middleware = [];
const store = createStore(
  reducer,
  0,
  compose(
    reactReduxFirebase,
    sagaPreinitMiddleware(sagas)
  )
);


// sagas.js
function* handle(action) {
  console.log(action);
}

function* sagas() {
  yield takeEvery('*', handle);
}

Журнал:

   00000000: [reducer] action Object {type: "@@redux/INIT"}
   00000008: [reducer] action Object {type: "DUMMY_ACTION"}
             Object {type: "DUMMY_ACTION"}
   00000011: [reducer] action Object {type: "DUMMY_ACTION_1"}
             Object {type: "DUMMY_ACTION_1"}
person DraganS    schedule 20.03.2017