11// 教程 12 - Provider-and-connect.js
22
3- // 我们的教程快结束了, 离对 Redux 有一个好的认识只差一步:
4- // 如何从 store 中的 state 读取, 和以及如何派发 actions ?
3+ // 我们的教程快结束了, 离对 Redux 有一个好的认识只差一步:
4+ // 如何从 store 中的 state 读取, 和以及如何派发 action ?
55
66// 这两个问题可以用 react-redux 的 connect 绑定一并解决。
77
8- // 如我们之前解释的, 当使用 Provider 组件的时候, 我们允许应用中所有组件访问 Redux。
8+ // 如我们之前解释的, 当使用 Provider 组件的时候, 我们允许应用中所有组件访问 Redux。
99// 但这个访问只能通过没有配备说明文档的功能 "React 的 context" 来完成。
10- // 为了避开这如"黑魔法"般的 React API , React-Redux 暴露了一个函数, 这样你就能在组件的类中使用它。
10+ // 为了避开这如"黑魔法"般的 React API , React-Redux 暴露了一个函数, 这样你就能在组件的类中使用它。
1111
12- // 我们讨论的这个函数就是 "connect" , 它能让我们用 Redux 的 store 字面值与组件连接上 。
13- // 这样一来, 它就能让你 store 中的 dispatch 函数通过组件的 props 传递,
14- // 而且可以添加任何你想暴露的属性, 这些暴露的属性将作为你 store 中 state 的一部分。
12+ // 我们讨论的这个函数就是 "connect" , 它能让我们用 Redux 中 store 的字面值与组件连接上 。
13+ // 这样一来, 它就能让你 store 中的 dispatch 函数通过组件的 props 传递,
14+ // 而且可以添加任何你想暴露的属性, 这些暴露的属性将作为你 store 中 state 的一部分。
1515
16- // 使用 "connect", 能仅用很少的代码将一个笨拙组件 (dumb component) 转换成一个智能组件 (smart component)
16+ // 使用 "connect", 能仅用很少的代码将一个笨拙组件 (dumb component) 转换成一个智能组件 (smart component)
1717// 参见: https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0
1818
1919// "connect" is a function that takes as parameters few mapping functions and that returns a function expecting
2020// the actual component class you want to connect.
2121// 这样一个函数(指 "connect") 被称之为高阶组件 (HOC, Higher Order Component)。
22- // 高阶组件(译者注: 原文为 Higher Order functions, 可能写错了)来源于"函数设计模式", 这种设计可以在不使用继承的情况下向其添加功能与行为 (component, store, ...)
23- // 这种方式有利于合成继承, 而且也是开发 React 应用的优先方法(但不是仅限的方法)。
22+ // 高阶组件(译者注: 原文为 Higher Order functions, 可能写错了)来源于"函数设计模式", 这种设计可以在不使用继承的情况下向其添加功能与行为 (component, store, ...)
23+ // 这种方式有利于合成继承, 而且也是开发 React 应用的优先方法(但不是仅限的方法)。
2424// 下面有更多关于高阶组件 (HOC) 与合成的文章:
2525// - https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750#.lpp7we7mx
2626// - http://natpryce.com/articles/000814.html
2727
28- // 高阶函数 "connect" 旨在解决所有, 从最简单到最复杂的使用情况。
29- // 在本例中, 我们不会用 "connect" 做很复杂的事,
28+ // 高阶函数 "connect" 旨在解决所有, 从最简单到最复杂的使用情况。
29+ // 在本例中, 我们不会用 "connect" 做很复杂的事,
3030// 但你可以去下面链接看看完整的 "connect" API 文档:
3131// https://github.com/rackt/react-redux/blob/v4.0.0/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options
3232
3939
4040// 我们只关注这里 "connect" 的第一个参数: mapStateToProps...
4141
42- // "connect" 接收了一个参数, 该参数是个函数, 它用于将你想要暴露给组件的数据片段从 state 中选取出来。
43- // 该函数逻辑上称之为 "selector", 它接收2个参数: 你 store 中的 state, 和当前组件的 props。
44- // 如下面所示, 我们将该函数命名为 "mapStateToProps"。
45- // 这个语义化的命名, 只是为了清晰表达该函数是用于: 将 state 映射(或解释为提取)到一些组件的 props 中。
46- // 组件的 props 还作为参数来提供, 就像通常从基于 state 中的 props 中提取数据片段一样,
42+ // "connect" 接收了一个参数, 该参数是个函数, 它用于将你想要暴露给组件的数据片段从 state 中选取出来。
43+ // 该函数逻辑上称之为 "selector", 它接收2个参数: 你 store 中的 state, 和当前组件的 props。
44+ // 如下面所示, 我们将该函数命名为 "mapStateToProps"。
45+ // 这个语义化的命名, 只是为了清晰表达该函数是用于: 将 state 映射(或解释为提取)到一些组件的 props 中。
46+ // 组件的 props 还作为参数来提供, 就像通常从基于 state 中的 props 中提取数据片段一样,
4747// 例如: state.items[props.someID]。
4848
4949// "mapStateToProps" 应该返回你想要暴露给组件的 props (一般通过一个字面量对象)。
50- // 这取决于在返回 state 时, 先转换接收到的 state。
50+ // 这取决于在返回 state 时, 先转换接收到的 state。
5151// 你可以看看下面 "connect" 的最简单用法(就在组件类的定义之后)。
5252
5353import React from 'react'
5454import { connect } from 'react-redux'
55- // 我们用 ES6 的 import 写法来获取所有的 action 创建函数, 如同我们在 reducers 中那样。
56- // 如果你还没看过我们的 action 创建函数, 转到 ./action-creators.js 去看看。
55+ // 我们用 ES6 的 import 写法来获取所有的 action 创建函数, 如同我们在 reducers 中那样。
56+ // 如果你还没看过我们的 action 创建函数, 转到 ./action-creators.js 去看看。
5757import * as actionCreators from './action-creators'
5858
5959class Home extends React . Component {
6060 onTimeButtonClick ( delay ) {
61- // 当用户点击这个按钮的时候, 该句柄会派发一个 action 来响应。
61+ // 当用户点击这个按钮的时候,该函数会派发一个 action 来响应。
6262 // 这里我们使用的 dispatch 函数由 props 中的 connect "自动"提供。
63- // 还有多种其他的方法来调用已经绑定到 dispatch 中的 actionCreator, 这意味着可以向 "connect" 提供第二个参数:
63+ // 还有多种其他的方法来调用已经绑定到 dispatch 中的 actionCreator, 这意味着可以向 "connect" 提供第二个参数:
6464 // https://github.com/rackt/react-redux/blob/v4.0.0/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options
65- // "delay" 的值传递给 actionCreators.getTime, 用于在获取当前时间之前模拟一次成功的异步操作。
66- // 尝试修改 delay 的值, 验证延迟是否正确影响了我们的 UI。
65+ // "delay" 的值传递给 actionCreators.getTime, 用于在获取当前时间之前模拟一次成功的异步操作。
66+ // 尝试修改 delay 的值, 验证延迟是否正确影响了我们的 UI。
6767 this . props . dispatch ( actionCreators . getTime ( delay ) )
6868 }
6969 render ( ) {
7070
71- // 要感谢 "connect", 我们能够通过 props 来获取已选择的具体的数据
71+ // 要感谢 "connect", 我们能够通过 props 来获取已选择的具体的数据
7272 var { frozen, time, reduxState } = this . props
7373 var attrs = { }
7474 const DELAY = 500 // 单位: 毫秒
@@ -101,13 +101,13 @@ class Home extends React.Component {
101101 }
102102}
103103
104- // 这个函数中, 我们将想通过 props 暴露给组件的数据片段从 state 中提取出来。
104+ // 这个函数中, 我们将想通过 props 暴露给组件的数据片段从 state 中提取出来。
105105const mapStateToProps = ( state /*, props*/ ) => {
106106 return {
107107 frozen : state . _time . frozen ,
108108 time : state . _time . time ,
109109 // 像下面这样 (reduxState: state) 将整个 state 都提供出去不太好,
110- // 这里这样写只是给你看一下, 更多相关请见:
110+ // 这里这样写只是给你看一下, 更多相关请见:
111111 // https://github.com/rackt/react-redux/blob/v4.0.0/docs/api.md#inject-dispatch-and-every-field-in-the-global-state
112112 reduxState : state ,
113113 }
@@ -117,25 +117,25 @@ const ConnectedHome = connect(mapStateToProps)(Home)
117117
118118export default ConnectedHome
119119
120- // 你也许注意到了, 正是要感谢 Redux, 在 state(当前时间下) 的驱动下我们有了动态的组件,
120+ // 你也许注意到了, 正是要感谢 Redux, 在 state(当前时间下) 的驱动下我们有了动态的组件,
121121// 该 state 在组件中并不扮演任何角色,
122122// 我们的组件仅仅只接收 props 中需要的数据。
123123// 这种组件称之为无状态的组件。在应用程序中你应该总是开发无状态的组件(如之前见过的的笨拙组件)。
124124// 因为无状态组件具有更高的复用性。
125- // 就像 "onTimeButtonClick" 句柄中建议的, 将点击回调通过 "connect" 的第二个参数 "mapDispatchToProps" 传递的时候, 我们可以做更多事情。
126- // 如此这般, 我们就可以将按钮的行为提取出来, 通过替换不同的点击动作, 使之有更高的复用性。
127- // 复用性似乎成了一个花哨且过度使用的概念, 但是可复用组件意味着, 它可以被很容易的测试, 因为你可以注入任何数据, 然后检查它是否处理正常, 确保它行为正确。
125+ // 就像 "onTimeButtonClick" 句柄中建议的, 将点击回调通过 "connect" 的第二个参数 "mapDispatchToProps" 传递的时候, 我们可以做更多事情。
126+ // 如此这般, 我们就可以将按钮的行为提取出来, 通过替换不同的点击动作, 使之有更高的复用性。
127+ // 复用性似乎成了一个花哨且过度使用的概念, 但是可复用组件意味着, 它可以被很容易的测试, 因为你可以注入任何数据, 然后检查它是否处理正常, 确保它行为正确。
128128
129- // 在转到 ./12_final-words.js 之前, 请先阅读一下这个旁注: 如何使用 "connect" 连接高阶组件的另外一种方法...
129+ // 在转到 ./12_final-words.js 之前, 请先阅读一下这个旁注: 如何使用 "connect" 连接高阶组件的另外一种方法...
130130
131- // 因为 connect(...) 返回2个东西: 接收一个类(class) 的函数, 和另外一个类(class),
132- // 如果你愿意的话, 可以使用 ES7 的修饰器(Decorator) 方法来写。
133- // 修饰器(Decorator) 是 ES7 中的实验性功能, 它使我们能在设计类与属性时对其进行修改,
131+ // 因为 connect(...) 返回2个东西: 接收一个类 (class) 的函数, 和另外一个类 (class),
132+ // 如果你愿意的话, 可以使用 ES7 的修饰器 (Decorator) 方法来写。
133+ // 修饰器 (Decorator) 是 ES7 中的实验性功能, 它使我们能在设计类与属性时对其进行修改,
134134// 更多请见: https://github.com/wycats/javascript-decorators
135135
136- // 该功能是实验性的, 它受制于语言标准的变化。
137- // 这意味着, 如果你使用了它, 你必须当心和接受标准演进所带来的不确定性。
138- // 修饰器提供了一个语法糖, 用它编码会和上面的代码有些小区别。
136+ // 该功能是实验性的, 它受制于语言标准的变化。
137+ // 这意味着, 如果你使用了它, 你必须当心和接受标准演进所带来的不确定性。
138+ // 修饰器提供了一个语法糖, 用它编码会和上面的代码有些小区别。
139139// 以前这样写:
140140
141141/*
@@ -150,7 +150,7 @@ export default ConnectedHome
150150 export default class MyClass {}
151151*/
152152
153- // 在 Redux 的 connect 中使用修饰器语法, 可以用:
153+ // 在 Redux 的 connect 中使用修饰器语法, 可以用:
154154
155155/*
156156 let mapStateToProps = (state) => { ... }
@@ -167,12 +167,12 @@ export default ConnectedHome
167167*/
168168
169169
170- // 如你所见, 组件类中的高阶组件函数写法更加含蓄了:
170+ // 如你所见, 组件类中的高阶组件函数写法更加含蓄了:
171171// @connect (mapStateToProps)
172172// 而不是我们自己调用它:
173173// @connect (mapStateToProps)(Myclass)
174- // 有些人觉得这样写更优雅, 但有的人不喜欢, 因为这样隐藏了背后真正发生的事情, 或是不理解修饰器是如何工作的。
175- // 记住, 修饰器目前为实验性功能, 如何使用 "connect" 取决于你自己,
176- // 在别处的文章、教程、项目模版中, 常可以看到这两种语法。
174+ // 有些人觉得这样写更优雅, 但有的人不喜欢, 因为这样隐藏了背后真正发生的事情, 或是不理解修饰器是如何工作的。
175+ // 记住, 修饰器目前为实验性功能, 如何使用 "connect" 取决于你自己,
176+ // 在别处的文章、教程、项目模版中, 常可以看到这两种语法。
177177
178178// 转到 ./12_final-words.js 去看我们最后的建议...
0 commit comments