Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing the state from within a redux-observable epic

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

like image 541
sra Avatar asked Dec 01 '16 15:12

sra


1 Answers

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.

like image 51
jayphelps Avatar answered Oct 17 '22 23:10

jayphelps