如何编写可重用和模块化的Redux选择器?

时间:2019-07-18 19:09:00

标签: javascript redux react-redux

我是Redux的新手,正在尝试弄清楚如何充分利用它。

为应用程序的模块编写选择器时,应将状态树的哪一部分传递给选择器,以使选择器既可重用又可模块化?

例如,给定下面的代码,什么是写状态状态类似于selectModuleItemsById的{​​{1}}的好方法?

stateShapeExample

2 个答案:

答案 0 :(得分:2)

简短的回答是,这很棘手。

我所见过的最好的文章是Randy Coulman关于模块化选择器的系列文章:

总体总结似乎是让“模块缩减器”编写选择器,这些选择器知道如何从自己的状态中挑选数据,然后根据模块/切片的安装位置在应用程序级别“全球化”它们在状态树中。但是,由于模块可能需要使用选择器本身,因此您可能必须将注册/设置过程移到单独的文件中,以避免循环依赖问题。

答案 1 :(得分:1)

根据定义,选择器将进入整个状态并返回该状态的一部分。基本上,其他所有功能都只是数据实用程序功能。

我使用ramda镜头来管理这种事情。

考虑这样的目录结构:

store
  module
    data.js
    selectors.js
    reducers.js
    actions.js

data.js将导出初始状态(在这种情况下,仅导出modules的初始状态)和描述状态块位置的ramda镜头。

import { lensPath } from 'ramda'

export default {
    items: {
        firstItemId: {...},
        secondItemId: {...},
        ...
    }
}

export const itemsLens = lensPath(['module', 'items'])
export const makeItemLens = id => lensPath(['module', 'items', id])

然后,在selectors.js中导入镜头以从整个状态树中选择数据。

import {view} from 'ramda'
import {itemsLens, makeItemLens} from './data.js'

export const selectModuleItems = state => view(itemsLens, state)
export const selectModuleItemById = (state, id) => view(makeItemLens(id), state)

此策略有一些好处:

  1. 将ramda的lensPathview结合使用可使您进行深入的属性查找,而不会冒Cannot read propery firstItemId of undefined错误的风险。如果ramda影响您的事物,其他库也具有等效的功能(lodash,immutable.js等)。
  2. 将镜头置于初始状态旁边可以为其他开发人员增加很多清晰度。
  3. 如果要提取镜头的对象路径,则可以更容易地重组状态树。

不利之处在于,这是一堆额外的样板代码,但是在显式且避免使用魔术代码IMO方面很有用。

说了这么多,您还应该查看reselect以获得更高级的选择器策略(我尚未广泛使用的方法)。