Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error: Before running a Saga, you must mount the Saga middleware on the Store using applyMiddleware

I wrote a simple counter app. I tried to add a saga middleware to log actions. Very basic app, but i nice structure.

When I add a middleware something went wrong: I had the error:

redux-saga-core.esm.js:1442 Uncaught Error: Before running a Saga, you must mount the Saga middleware on the Store using applyMiddleware
    at Function.sagaMiddleware.run (redux-saga-core.esm.js:1442)
    at createAppStore (Store.tsx:66)
    at eval (Store.tsx:70)
    at Module../src/store/Store.tsx (bundle.js:1175)
    at __webpack_require__ (bundle.js:20)
    at eval (App.tsx:6)
    at Module../src/components/App.tsx (bundle.js:1127)
    at __webpack_require__ (bundle.js:20)
    at eval (index.tsx:6)
    at Module../src/index.tsx (bundle.js:1151)

I found the problem is the  initialiseSagaMiddleware.run(sagaLogger);
but why? It comes just after createStore...

Here my store:

/**
 * This is the global store, where the magic appens. Here I have a redurcer who generates
 * the new application state and the global state.
 * Store = cotainer of reducer and state.
 */

import react from "react";
import { createStore, applyMiddleware,  } from "redux";
import {IState,IAction, actionType} from '../types/types'
import createSagaMiddleware from "redux-saga";
import {sagaLogger} from '../middleware/sagaLogger'

const initialiseSagaMiddleware = createSagaMiddleware();

/**
 * Application initial state. TODO: may be loaded from an API?
 */
const initialState : IState = {
    count: -10
}

/**
 * Reducer: function that create a new state. I must be a pure function, no side effects.
 * It works only on his parameter and return the new state. Reducer parameter are always the same.
 * @param state application global state, ad default it has initialState value.
 * @param action action fired by components. 
 */
  const reducer = (state: IState = initialState, action: IAction): IState => { //Set default to initialState
   // console.log(state, action);
    const newState : IState = { count: state.count}
    switch(action.type){
        case actionType.INCREMENT:
            newState.count= newState.count+1;
            break;
        case actionType.DECREMENT:
            newState.count=newState.count-1;
            break;
        default:
            newState.count= newState.count;
            break;
    }
    return newState;
  };



  /**
   * AppStore is my store. createStore create my Redux Store.
   * TODO: change any to <IState,IAction>
   * For use with redux dev tool use: storeEnhancers, compose
   */
  const sagaMiddleware = createSagaMiddleware();
  const createAppStore = (): any => {

        const Store = createStore(
          reducer,
          applyMiddleware(sagaMiddleware)
        );
       initialiseSagaMiddleware.run(sagaLogger);
        return Store;
  }


export const AppStore = createAppStore();

Here my app.tsx

import React from 'react'
import {Provider} from 'react-redux'
import  {AppStore} from "../store/Store";
import Counter from "./counter";

/**
 * Provider is part of the Redux magic. It connect react to redux providing to all the children components (all levels) the state.
 */

export default function App():JSX.Element {
    return (
      <Provider store = {AppStore}>
        <div>
          <Counter />
        </div>
      </Provider>
    );
}

Here my banbel.rc (I had to define env preset):

 {
        "presets": [
            [
                "@babel/preset-env",
                {
                    "targets": {
                        "browsers": [
                            "last 2 Chrome versions"
                        ]
                    }
                }
            ],"@babel/react","@babel/Typescript"]
    }

I hope my counter works and action will be logged on the console.

like image 477
Matteo Fioroni Avatar asked Aug 01 '19 20:08

Matteo Fioroni


1 Answers

You are creating two saga middlewares and applying one to the store and running your sagas on the other. Remove the const initialiseSagaMiddleware = createSagaMiddleware(); and change createAppStore to:

  const sagaMiddleware = createSagaMiddleware();
  const createAppStore = (): any => {

        const Store = createStore(
          reducer,
          applyMiddleware(sagaMiddleware)
        );
       // use the same saga middleware that you have enhanced your store with
       sagaMiddleware.run(sagaLogger);
        return Store;
  }
like image 93
azundo Avatar answered Nov 15 '22 05:11

azundo