非常教程

Redux参考手册

FAQ

Redux FAQ: React Redux

目录

  • 为什么不是我的组件重新渲染,或我的 mapStateToProps 运行?
  • 为什么我的组件经常重新渲染?
  • 我怎样才能加快我的 mapStateToProps?
  • 为什么我没有在连接组件中使用 this.props.dispatch?
  • 我应该只连接顶层组件,还是可以连接树中的多个组件?

React Redux

为什么不是我的组件重新渲染,或我的 mapStateToProps 运行?

直接意外地改变或修改你的状态是迄今为止,组件在调度动作后不重新渲染的最常见原因。Redux 希望你的减员会“不变”地更新他们的状态,这实际上意味着总是复制你的数据,并将你的修改应用到副本中。如果您从还原器返回相同的对象,Redux 会假定没有任何更改,即使您对其内容进行了更改。同样,shouldComponentUpdate中的 React Redux 会尝试通过对传入道具进行浅平等引用检查来提高性能,如果所有引用都相同,则返回false跳过实际更新原始组件。

重要的是要记住,无论何时更新嵌套值,还必须在状态树中返回其上的任何新副本。如果你有state.a.b.c.d,你想使一个更新d,您还需要返回的新副本cba,和state。此状态树突变图演示了树中的深度变化需要如何改变。

请注意,“更新数据不可改变”不意味着你必须使用Immutable.js,尽管这肯定是一种选择。你可以使用几种不同的方法对普通的JS对象和数组进行不可变的更新:

  • 使用的功能,如复制的对象Object.assign()_.extend(),并且阵列的功能,例如slice()concat()
  • ES6中的阵列扩展运算符,以及为将来版本的JavaScript提出的类似对象扩展运算符
  • 将不可变更新逻辑包装成简单函数的实用程序库

更多信息

文档

  • Troubleshooting(故障排除)
  • React Redux: Troubleshooting(React Redux:疑难解答)
  • Recipes: Using the Object Spread Operator(使用对象传播操作符)
  • Recipes: Structuring Reducers - Prerequisite Concepts(构建Reducers - 先决条件的概念)
  • Recipes: Structuring Reducers - Immutable Update Patterns(构建 Reducers - 不变的更新模式)

文章

  • Pros and Cons of Using Immutability with React(反应法使用不变性的优缺点)
  • React/Redux Links: Immutable Data(React/Redux链接:不可变数据)

讨论

  • #1262: Immutable data + bad performance(不可变的数据+糟糕的表现)
  • React Redux #235: Predicate function for updating component(用于更新组件的谓词函数)
  • React Redux #291: Should mapStateToProps be called every time an action is dispatched?(每次调度操作时,是否应调用 mapStateToProps?)
  • Stack Overflow: Cleaner/shorter way to update nested state in Redux?(堆栈溢出:更新/更短的方式来更新 Redux 中的嵌套状态?)
  • Gist: state mutations(要点:状态突变)

为什么我的组件经常重新渲染?

React Redux 实现了几个优化,以确保实际组件只在实际需要时重新渲染。其中之一是对由传递给mapStateToProps和的mapDispatchToProps参数生成的组合道具对象进行浅层等式检查connect。不幸的是,在每次mapStateToProps调用新创建的数组或对象实例的情况下,浅的平等不起作用。一个典型的例子可能是映射一个ID数组并返回匹配的对象引用,例如:

const mapStateToProps = state => {
  return {
    objects: state.objectIds.map(id => state.objects[id])
  }
}

即使数组可能每次都包含完全相同的对象引用,但数组本身是不同的引用,因此浅平等检查失败,并且 React Redux 将重新呈现包装组件。

额外的重新渲染可以通过使用 reducer 将对象数组保存到状态,使用 Reselect 缓存映射的数组,或者shouldComponentUpdate手动实现组件并使用一个函数(例如)执行更深入的道具比较来解决_.isEqual。注意不要让自定义shouldComponentUpdate()比渲染本身更昂贵!始终使用分析器来检查您对性能的假设。

对于未连接的组件,您可能需要检查传入的道具是什么。常见问题是父组件在其渲染函数内重新绑定回调,例如<Child onClick={this.handleClick.bind(this)} />。每次父级重新呈现时,都会创建一个新的函数引用。在父组件的构造函数中只绑定一次回调通常是很好的做法。

更多信息

文档

  • FAQ: Performance - Scaling(性能缩放)

文章

  • A Deep Dive into React Perf Debugging(深入研究React Perf调试)
  • React.js pure render performance anti-pattern(React.js纯粹渲染性能反模式)
  • Improving React and Redux Performance with Reselect(用重新选择提高 React 和 Redux 的性能)
  • Encapsulating the Redux State Tree(封装 Redux 状态树)
  • React/Redux Links: React/Redux Performance(React/Redux链接:React/Redux性能)

讨论

  • Stack Overflow: Can a React Redux app scale as well as Backbone?(堆栈溢出:React Redux 应用程序可以像 Backbone 一样扩展吗?)

Libraries

  • Redux Addons Catalog: DevTools - Component Update Monitoring

我如何加快我的速度mapStateToProps

尽管 React Redux 可以最大限度地减少mapStateToProps调用函数的次数,但确保mapStateToProps快速运行并尽量减少工作量仍然是一个不错的主意。常用的推荐方法是使用 Reselect 创建 memoized“选择器”功能。这些选择器可以组合在一起,稍后在管道中的选择器只有在其输入发生变化时才会运行。这意味着您可以创建选择器来执行筛选或排序等任务,并确保只有在需要时才会发生实际工作。

更多信息

文档

  • Recipes: Computed Derived Data(计算派生数据)

文章

  • Improving React and Redux Performance with Reselect(用重新选择提高 React 和 Redux 的性能)

讨论

  • #815: Working with Data Structures(使用数据结构)
  • Reselect #47: Memoizing Hierarchical Selectors(记忆分层选择器)

为什么我不能在我的连接组件中使用this.props.dispatch?

connect()函数有两个主要参数,都是可选的。第一个,mapStateToProps是你提供的一个函数,当它改变时从商店中提取数据,并将这些值作为道具传递给你的组件。第二个,mapDispatchToProps是你提供的一个函数,可以使用商店的dispatch功能,通常通过创建动作创建者的预先绑定版本,一旦被调用就会自动发送他们的动作。

如果您的mapDispatchToProps在调用时没有提供自己的功能connect(),React Redux 将提供一个默认版本,它只是将该dispatch函数作为道具返回。这意味着,如果你做的提供自己的功能,dispatch不会自动提供。如果你仍然希望它可以作为道具,你需要在你的mapDispatchToProps实现中自己明确地返回它。

更多信息

文档

  • React Redux API: connect()

讨论

  • React Redux #89: can i wrap multi actionCreators into one props with name?(React Redux#89:我可以将多个 actionCreators 包装成一个名称为 props 的道具吗?)
  • React Redux #145: consider always passing down dispatch regardless of what mapDispatchToProps does(React Redux#145:不管 mapDispatchToProps 是做什么的,都要考虑总是向下传递)
  • React Redux #255: this.props.dispatch is undefined if using mapDispatchToProps(React Redux#255:如果使用 mapDispatchToProps,则 this.props.dispatch 未定义)
  • Stack Overflow: How to get simple dispatch from this.props using connect w/ Redux?(堆栈溢出:如何使用连接w/Redux从this.props获得简单分发?)

我应该只连接顶层组件,还是可以连接树中的多个组件?

早期的 Redux 文档建议您应该只在组件树顶部附近有几个连接的组件。然而,时间和经验表明,通常需要少数组件来了解所有后代的数据需求,并迫使它们传递混乱的道具数量。

当前建议的最佳做法是将组件分类为“呈现”或“容器”组件,并在任何有意义的地方提取连接的容器组件:

Redux 示例中强调“顶部的一个容器组件”是一个错误。不要把这当成一句格言。尽量让您的演示文稿组件分开。在方便时通过连接来创建容器组件。每当你觉得你正在复制父组件中的代码来为相同种类的孩子提供数据时,就需要花费时间来提取一个容器。一般情况下,只要您觉得父级对子的“个人”数据或行为知之甚多,就有时间提取容器。

事实上,基准测试表明,连接的组件越多,连接组件的数量越少,性能越好。

一般来说,尝试在可理解的数据流和组件的责任区域之间找到平衡点。

更多信息

文档

  • Basics: Usage with React(基础:使用React)
  • FAQ: Performance - Scaling(性能—缩放)

文章

  • Presentational and Container Components(展示和容器组件)
  • High-Performance Redux(高性能Redux)
  • React/Redux Links: Architecture - Redux Architecture(React/Redux链接:体系结构 - Redux体系结构)
  • React/Redux Links: Performance - Redux Performance(React/Redux 链接:性能 - Redux 性能)

讨论

  • Twitter: emphasizing “one container” was a mistake(Twitter:强调“一个容器”是一个错误)
  • #419: Recommended usage of connect(建议使用连接)
  • #756: container vs component?(容器vs组件?)
  • #1176: Redux+React with only stateless components(Redux +仅与无状态组件进行反应)
  • Stack Overflow: can a dumb component use a Redux container?(堆栈溢出:愚蠢的组件可以使用 Redux 容器吗?)
Redux

Redux由Dan Abramov在2015年创建的科技术语。是受2014年Facebook的Flux架构以及函数式编程语言Elm启发。很快,Redux因其简单易学体积小在短时间内成为最热门的前端架构。

主页 http://redux.js.org/
源码 https://github.com/reactjs/redux/
发布版本 3.7.2

Redux目录

1.高级 | Advanced
2.API
3.基础 | Basics
4.FAQ
5.介绍 | Introduction
6.其他 | Miscellaneous
7.方法 | Recipes