I am using redux to build a little fusball-manager. Basically it's a page that shows the score of both teams and some buttons to increment them. I have actions like { type:"GOAL_UP", team:"red" }
for which the reducer will change the corresponding value (score) in the state.
Now I want to add an epic that whenever it encounters a GOAL_UP
checks if one of the two teams has won the game. If a team has reached a score of 8, I want it to dispatch a GAME_WON
action. My problem is that I have to access the state to know the score of each team. I cannot find a way to access the state from within an epic.
Is accessing the state out of scope for redux-observable? If so, how would you solve this problem?
I am thinking about having the new score as a property in the GOAL_UP
action. Something like this { type:"GOAL_UP", team:"red", newScore:8 }
. But somehow this feels wrong. I also have two physical buttons on the fusball-table that are connected with web sockets, which dispatch the GOAL_UP
action. Since they are not triggered from my ui they don't know about the state.
I could also think of dispatching the GAME_WON
action in the render function of my ui component if the score of either team is 8. But that feels even more wrong :)
Input is very welcome, Thanks
Check out the Accessing the Store's State section of the redux-observable docs.
It describes how, in addition to a stream of actions (the first argument), your epics receive a stream of store states (second argument).
Use state$.value
to synchronously access the current state. This value will contain your entire redux store state.
Note that by the time an action reaches your epic it has already be run through your reducers (and any state updated).
const INCREMENT = 'INCREMENT';
const INCREMENT_IF_ODD = 'INCREMENT_IF_ODD';
const increment = () => ({ type: INCREMENT });
const incrementIfOdd = () => ({ type: INCREMENT_IF_ODD });
const incrementIfOddEpic = (action$, state$) =>
action$.ofType(INCREMENT_IF_ODD)
.filter(() => state$.value.counter % 2 === 0)
.map(increment);
// later...
dispatch(incrementIfOdd());
I would also add that as described, I don't think you need redux-observable or even redux for this--it's rather overkill. Of course, if this is just to get your feet wet and learn, by all means! Just don't want you to think you need these complex abstractions for simple things.