我是Redux的新手,正在尝试弄清楚如何充分利用它。
为应用程序的模块编写选择器时,应将状态树的哪一部分传递给选择器,以使选择器既可重用又可模块化?
例如,给定下面的代码,什么是写状态状态类似于selectModuleItemsById
的{{1}}的好方法?
stateShapeExample
答案 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)
此策略有一些好处:
lensPath
与view
结合使用可使您进行深入的属性查找,而不会冒Cannot read propery firstItemId of undefined
错误的风险。如果ramda影响您的事物,其他库也具有等效的功能(lodash,immutable.js等)。不利之处在于,这是一堆额外的样板代码,但是在显式且避免使用魔术代码IMO方面很有用。
说了这么多,您还应该查看reselect以获得更高级的选择器策略(我尚未广泛使用的方法)。