React.js/Redux: setInterval and clearInterval in Reducers

Alejandro picture Alejandro · Sep 18, 2016 · Viewed 7.6k times · Source

Currently I am working on FCC Game of Life and I was able figure out how to generate the next app state (incrementally).

That being said, my next step is to figure out how to generate new app state (generation) continuously. In this case, I am trying to implement setInterval and clearInterval inside my reducer.

I'd like to have the ability to start/pause generating new generation (by toggling the state in state.start)

The thing I am having trouble of implementing it is the scope issue.

Here's part my reducer:

reducers/reducers_grid.js

export default function(state = initialState, action){
  switch (action.type) {
    ....
    case START:
      let toggleStart = state.start === true ? false : true;

      if (state.start === true){
        console.log('START THE GAME')

        const newGeneration = nextGeneration(action.payload,state)
        return Object.assign({}, state, {cells: newGeneration, start: toggleStart })
      }
      else {
        console.log('PAUSE THE GAME')
        return Object.assign({}, state, {start: toggleStart })
      }

  return state;
}

Essentially, nextGeneration function results the new app state (generation) and updates it to via Object.assign

At first, I thought putting setInteveral inside the first if statement and clearInterval in the second if statement, but obviously that will create a scope issue.

It seems very trivial this part of logic, but I've been stuck on this awhile.

Answer

Jack Noble picture Jack Noble · Sep 19, 2016

Don't do this in the reducer. Reducers should be pure functions (meaning no side-effects). Instead, you could create a component that is rendered only when the game is running (a boolean state which is set to true by the START action and false by the STOP action). Then in the component's componentDidMount function call setInterval with a function that dispatches a NEXT_GENERATION action. After that dispatch another action which adds the timer id to the store. Then, in the componentWillUnmount call clearInterval with the timer id.