Search code examples
reactjstypescriptreduxredux-sagaredux-reducers

Reducer doesn't catch action


I'm working on an existing project with working Redux Saga. Everything is already setup (action creators, action types, reducer, selectors, sagas…). I wanted to add a piece of code which should set a flag in the state, and then I want to render something conditionally depending on that flag's value.

mySaga.ts

...
if (someCondition) {
  // I put a console.log here and made sure that this part was executed.
  doSetMyFlag();
  // I also tried with "yield doSetMyFlag()"
}
...

myActionCreators.ts

...
// I copied and pasted an identical working method and just changed names:
// I also put console.log and I know that this part is getting executed.
export const doSetMyFlag = () => ({
  type: MY_ACTION_TYPE
} as const);
...

myActionTypes.ts

// Again, copied an existing type and renamed it:
export const MY_ACTION_TYPE = '@@RESULTS/MY_ACTION_TYPE' as const;

myReducer.ts

// A working reducer, already added to the place where all reducers are combined:
...
case MY_ACTION_TYPE: {
  // console.log WASN'T executed here, and I have no idea why...
  return {
    ...state,
    isMyFlag: true,
  }
}
...

mySelectors.ts

// This is getting executed, but it's always returning false, since the code in the reducer wasn't executed and didn't set the flag to true.
export const getIsMyFlag = (rootState: State): boolean => getState(rootState).isMyFlag;

Finally, in my component I'm using the selector to get the current state of myFlag, and then I want to render something conditionally.

myComponent.ts

const myFlag = useSelector(getIsMyFlag);
// I already have an identical line with different selector, so this should work
...
{ myFlag && <div>The content that I want</div> }
// This doesn't get rendered, since getIsMyFlag always returns false

I have written a reducer test, and it was green:

export const initialState = { isMyFlag:false };
export const stateWithMyFlagTrue = { isMyFlag: true };
...
expect(reducer(initialState, doSetMyFlag())).toStrictEqual(stateWithMyFlagTrue);

I also have a selector test, also green:

expect(getIsMyFlag(rootState)).toBe(rootState.isMyFlag);`

As I wrote in the code comments, the reducer didn't catch the action and didn't execute the code in case MY_ACTION_TYPE. What am I doing wrong?


Solution

  • You must use the put function to dispatch an action inside of a saga.

    import { put } from 'redux-saga/effects'
    
    if (someCondition) {
       yield put(doSetMyFlag());
    }
    

    Right now you are calling the action creator but not doing anything with the resulting action.


    Redux Saga Docs: