Redux reducer 中的副作用

Side effects in Redux reducer

Redux 减速器应该没有副作用。但是如果一个动作应该触发浏览器中的文件下载,其中内容基于商店的状态呢?这当然应该算作副作用吗?像下面这样的方法可以吗,还是我应该寻找替代方法?

case 'SAVE_GRID': {
  const { json } = state
  fileDownload(json, 'data.json', 'application/json')
  return state
}

有库可以处理这种 "side" 效果。

例如:

  • redux-observables:他们在底层使用 RX observables。

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

  • redux-saga

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

除非你有非常复杂的状态转换,否则实际的 fileDownload 应该发生在 action creator 中,而不是在 reducer 中。 reducer 应该负责 merging/reducing 状态,仅此而已。

操作:

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

减速器:

case 'SAVE_GRID': {
    return {
        ...state,
        json: action.json
    }
}

Reducers 可以 驱动效果,事实上,它们一直通过触发 UI 渲染的状态变化来实现——可以说是应用程序最重要的效果。

驱动 non-visual 效果并不常见,但至少有两种解决方案:redux-loop 和 redux-agent(我写的)。

来自各自的站点:

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/

(引号还暗示了两者之间的主要区别:redux-loop returns 来自减速器的效果描述,从而改变了它的 API 并需要存储增强器。redux-agent 与原版 Redux 一起工作 API。)

我使用钩子 useReducer 代替 redux。我不喜欢在 action creator 中加入副作用 - 那么不清楚 action creator 的目的是什么:构建一个动作,还是 运行 side effects?

我在这里找到了满足我目的的图书馆:

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