Side effects in Redux reducer
Asked Answered
B

4

8

Redux reducers should be without side-effects. But what if an action should trigger the download of a file in the browser where the content is based on the state of the store? Surely this should count as a side effect? Would something like the following be fine or should I be looking for alternative methods?

case 'SAVE_GRID': {
  const { json } = state
  fileDownload(json, 'data.json', 'application/json')
  return state
}
Birdsall answered 15/12, 2017 at 13:55 Comment(0)
D
8

Unless you have very complex state transitions, the actual fileDownload should happen in an action creator, not in the reducer. The reducer should be responsible for merging/reducing state and that is all.

action:

export const saveGrid = (json) => {
   return (dispatch) => {  
       fileDownload(json, 'data.json', 'application/json')
           .then(() => {
              dispatch({ type: 'SAVE_GRID', json });
           });
   }
}

reducer:

case 'SAVE_GRID': {
    return {
        ...state,
        json: action.json
    }
}
Devest answered 15/12, 2017 at 14:6 Comment(1)
For anyone who maybe is not already aware, you'll need a middleware like redux-thunk to be able to dispatch a function as an action like this.Arana
D
1

There are libraries to handle such "side" effects.

For example:

  • redux-observables: they use RX observables under the hood.

https://redux-observable.js.org/docs/basics/Epics.html

  • redux-saga

https://redux-saga.js.org/

Doubletalk answered 15/12, 2017 at 14:4 Comment(0)
D
0

Reducers can drive effects, in fact they do it all the time via state changes which trigger UI rendering — arguably the application's most important effect.

Driving non-visual effects isn't as common but there are at least two solutions: redux-loop and redux-agent (which I wrote).

From the respective sites:

redux-loop:

A port of the Elm Architecture to Redux that allows you to sequence your effects naturally and purely by returning them from your reducers. https://redux-loop.js.org/

redux-agent:

Redux Agent extends React’s model to non-visual I/O: describe a network request, a storage operation, a websocket message, … and let the machine worry about performing it. Logic stays in the reducer, components stay lightweight, and it’s easy to see what state triggers which effect. https://redux-agent.org/

(The quotes also hint at a major difference between the two: redux-loop returns effect descriptions from the reducer, thereby changing its API and requiring a store enhancer. redux-agent works with vanilla Redux API.)

Dowdell answered 10/7, 2019 at 15:33 Comment(0)
S
0

I use the hook useReducer in lieu of redux. I'm not a fan of putting side effects in action creators - then it is unclear what the purpose of the action creator is: build an action, or run side effects?

I found a library here that fulfills my purpose:

https://github.com/Jibbedi/use-reducer-effect

Sticker answered 27/6, 2021 at 3:44 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.