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?
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: