Reactjs Redux 我们应该为状态树中的每个对象创建 sub reducer 吗?
Posted
技术标签:
【中文标题】Reactjs Redux 我们应该为状态树中的每个对象创建 sub reducer 吗?【英文标题】:Reactjs Redux should we create sub reducer for every object in the state tree? 【发布时间】:2017-01-04 18:53:41 【问题描述】:据我所知,redux 应用程序维护状态树的正确方法是对其进行规范化,尽可能扁平化数据并使用 combinereducer 创建状态树的切片。
具有帖子和用户的示例应用
const rootReducer = combineReducers(
user:userReducer,
posts:postsReducer,
);
const store = createStore(rootReducer);
给定帖子数组保持所有帖子初始化,State.posts
看起来像
let initialState =
byId:1:id:1,title:'post1',
ids:[1],
meta_data:unread:1,old:0
现在,如果我们有大约 10,000 个帖子,我们最终会得到 state.post.ids.length === 10000
,这很好,
问题是。因为我们的 reducer 每次需要更新时都会返回一个新状态,例如我们需要更新 meta_data.unread 为等于 0,我们将返回一个新的 Post 对象。
return object.assign(,state,meta_data:unread:0,old:1)
这将重新渲染所有使用state.post
树属性的选择器和组件!
这听起来像个问题对吗?** 我们想要的只是更新未读计数器.. 为什么要重新计算 Posts 的所有选择器和组件?
所以我有这个想法,可能是 state.posts 也应该使用 combineReducers 组成,以便每个 attr.的帖子应该有一个自己的减速器。
将postsReducer拆分成多个
postsMainReducer, ==> deal with adding or removing posts
postMeta_dataReducer, ==> deal with meta_data of posts
singlePostReducer ==> Now this is dynamic !! how can i create such ??
这是正确的吗?我增加了比需要更多的复杂性?
-->谁能给我们看一张已经在运行的企业应用状态树的图片?所以我们可以从中学习如何组织状态?
【问题讨论】:
【参考方案1】:需要注意的是,一个 Redux 存储实际上只有一个 reducer 函数。存储将当前状态和分派的操作传递给该减速器函数,并让减速器适当地处理事情。
显然,试图在单个函数中处理所有可能的操作并不能很好地扩展,仅就函数大小和可读性而言,因此将实际工作拆分为可由顶层调用的单独函数是有意义的减速器。特别是,常见的建议模式是拥有一个单独的 sub-reducer 函数,负责管理对特定键的特定状态片的更新。 Redux 附带的 combineReducers() 是实现这一目标的众多可能方法之一。还强烈建议让您的商店状态尽可能平坦和规范化。但最终,您将负责以任何您想要的方式组织您的 reducer 逻辑。
然而,即使你碰巧有许多不同的独立子减速器,甚至有深度嵌套的状态,减速器的速度也不太可能成为问题。 javascript 引擎每秒能够运行大量的函数调用,并且您的大多数子缩减程序可能只是使用 switch 语句并默认返回现有状态以响应大多数操作。
如果你真的关心 reducer 的性能,你可以使用 redux-ignore(https://github.com/omnidan/redux-ignore) 或 reduxr-scoped-reducer(https://github.com/chrisdavies/reduxr-scoped-reducer) 等实用程序来确保只有特定的 reducer 监听特定的操作。你也可以使用 redux-log-slow-reducers(https://github.com/michaelcontento/redux-log-slow-reducers) 做一些性能基准测试。
这是我最常参考的项目-
这些是 Redux 的实际用途。
这里有一些链接:
https://github.com/andrewngu/sound-redux
https://github.com/echenley/react-news
https://github.com/paulhoughton/remember/
https://github.com/paulhoughton/mortgage/
https://github.com/benoitvallon/react-native-nw-react-calculator
https://github.com/jfurrow/flood
https://github.com/FH-Potsdam/shifted-maps
https://github.com/quirinpa/2post
https://github.com/karlguillotte/Ctfs
https://github.com/madou/gw2armory.com
【讨论】:
只是添加到这个;真正的答案是“不要过早优化”。 React 和 Redux 旨在即使在大量数据下也能非常快速地运行。让他们做他们的工作。等到您发现问题后再尝试解决(如果您想尽早看到问题,请进行基准测试)。【参考方案2】:这将重新渲染所有使用任何选择器和组件 state.post 树的属性!
这并不确定,当商店的无关属性发生变化时,组件不必重新渲染。如果您的组件是PureComponent,则当属性的引用(原始道具的值)等于它们上次渲染的值时,它将不会重新渲染。
var foo = a: [1, 2, 3], someCount: 1 ;
var bar = Object.assign(, foo, someCount: 2 );
console.log(foo.a === bar.a);
// true
reducer 中返回的状态确实是一个新对象,但你的帖子数组在分配之后仍然是同一个数组(相等引用)。所以如果你使用 PureComponent,React 可以很好地处理这个问题。
接下来您可能会偶然发现:如果您在选择器中使用从商店或多个商店派生的派生数据,则可以使用reselect 到memoize 结果,这样引用保持不变 - 无需重复需要渲染。 An article describes the problem with creating new arrays for derived or empty data in each render cycle.
【讨论】:
以上是关于Reactjs Redux 我们应该为状态树中的每个对象创建 sub reducer 吗?的主要内容,如果未能解决你的问题,请参考以下文章