11// 教程 12 - Provider-and-connect.js
22
3- // 到这为止我们的教程就基本上结束了, 关于Redux唯一剩下的问题
4- // 就是我们如何能读取store里面的state以及如何进行action的分发 。
3+ // 到这为止我们的教程就基本上结束了, 关于 Redux 唯一剩下的问题
4+ // 就是我们如何能读取 store 里面的 state 以及如何进行action的分发 。
55
6- // 这两个问题都能够使用connect去解决 。
6+ // 这两个问题都能够使用 Connect 去解决 。
77
8- // 正如我们前面所讲解的, 当我们使用Provider组件时 , 我们允许我们应用中的所有组件访问Redux.
9- // 但是这种访问只能使用不正式的特性React 's context来实现 ,
10- // 为了避免这种"黑科技"式 (不规范) 的API调用 ,
11- // React-Redux为我们暴露了一个组件中的函数让我们可以使用 。
8+ // 正如我们前面所讲解的, 当我们使用 Provider 组件时 , 我们允许我们应用中的所有组件访问Redux.
9+ // 但是这种访问只能使用不正式的特性 React 's context 来实现 ,
10+ // 为了避免这种"黑科技"式 (不规范) 的 API 调用 ,
11+ // React-Redux 为我们暴露了一个组件中的函数让我们可以使用 。
1212
13- // 这个函数就是Connect, 它让我们可以实现一个组件和Redux store的绑定 ,
14- // 通过这种绑定可以让store通过组件的属性(prop)分发函数,
13+ // 这个函数就是 Connect , 它让我们可以实现一个组件和 Redux store 的绑定 ,
14+ // 通过这种绑定可以让store通过组件的属性 (prop) 分发函数,
1515// 也可以根据我们自己的需要增加任何需要暴露的属性作为store里面state的一部分。
1616
17- // 使用了Connect , 你可以通过添加很少的代码让一个组件变得更"聪明",
17+ // 使用了 Connect , 你可以通过添加很少的代码让一个组件变得更"聪明",
1818// (https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0).
1919
20- // "connect" is a function that takes as parameters few mapping functions and that returns a function expecting
21- // the actual component class you want to connect. Such a function (connect) is called a Higher Order Component (HOC).
22- // Higher Order functions comes from a functional pattern designed to add features / behaviors to
23- // their inputs (component, store, ...) without using inheritance. This approach favors composition over inheritance
24- // which is the prefered way to build React applications (actually this is not limited at all to React applications).
25- // Read more about HOCs and composition here :
20+ // Connect 是一个接受一些映射函数作为参数, 并返回一个你想要链接的组件类函数, 的函数.
21+ // 这样的函数被叫做高层组件 ( Higher Order Component (HOC))
22+ // HOC 函数是一种在不修改继承的情况下能够添加特性和行为到输入 (component, store) 中的函数模式。
23+ // 这种方式比较继承更强调构成,
24+ // 这也是创建 React 应用更建议的方式 (其实并没有这个限制)
25+ // 阅读更多关于 HOC 和 composition 的文档 :
2626// - https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750#.lpp7we7mx
2727// - http://natpryce.com/articles/000814.html
2828
29- // The "connect" HOC is designed to address all use-cases, from the most simple to the most
30- // complex ones. In the present example, we're not going to use the most complex form of 'connect' but
31- // you can find all information about it in the complete 'connect' API documentation here:
29+ // Connect "HOC" 主要被设计用于解决无论简单和困难的使用场景。
30+ // 在现有的例子中, 我们不会使用 Connect 最复杂的形式,
31+ // 但是你可以在完整的 API 文档中找到有关的全部信息:
3232// https://github.com/rackt/react-redux/blob/v4.0.0/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options
3333
34- // Here is the complete 'connect' signature :
34+ // 以下是完整的 Connect 特征 :
3535// connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
36- // and here is how you're supposed to use it :
36+ // 它的使用方法如下 :
3737/*
3838 const wrappedComponentClass = connect(...)(ComponentClass)
3939*/
4040
41- // We will only focus here on the first 'connect' parameter : mapStateToProps...
41+ // 我们在这里会主要讲解 Connect 的第一个参数 : mapStateToProps
4242
43- // "connect" takes, as its first parameter, a function that will select which slice of your
44- // state you want to expose to your component. This function is logically called a "selector" and
45- // receives 2 parameters: the state of your store and the current props of your component.
46- // You'll see below that we named this function "mapStateToProps". This name is just a semantic name
47- // for our function that clearly expresses what the function does: it maps (read "extracts some of")
48- // the state to a few component props.
49- // The props of the component are also provided as arguments to handle common cases like extracting a slice of your
50- // state depending on a prop value (Ex: state.items[props.someID]).
51- // "mapStateToProps" is expected to return the props that you wish to expose to your component (usually via
52- // an object literal). It's up to you to eventually transform the state you're receiving before returning it.
53- // You can have a look right at that simplest 'connect' usage below (just after the component class definition).
43+ // Connect 将一个选择你想要将哪一些 state 暴露给组件的函数作为第一个参数。
44+ // 这个函数我们一般称它为 Selector。
45+ // 它需要接受两个参数: 当前 store 的状态 (state) 以及当前组件的 prop。
46+ // 可以看见我们将这个函数命名为 "mapStateToProps",
47+ // 这个名字从字面意义上告诉我们它的作用:
48+ // 它创造了从 state 到一些组件 props 的映射 (map)
49+
50+ // 为了完成提取部分组建的 props 作为 state 的动作, (Ex: state.items[props.someID]).
51+ // 组件的 props 也被作为参数提供。
52+ // "mapStateToProps" 被期望返回所有你希望暴露给你的组件的 props, 通常通过一个对象常量 (object literal)返回。
53+ // 你可以在返回前修改取得的 state 值。下面是一些简单的 Connect 应用 (在定义组件之后)
5454
5555import React from 'react'
5656import { connect } from 'react-redux'
57- // We use the same ES6 import trick to get all action creators and produce a hash like we did with
58- // our reducers. If you haven't yet, go get a look at our action creator (./action-creators.js).
57+ // 我们会使用一些 ES6 中的 import 技巧来得到所有的 action creator 并生成一个哈希值,
58+ // 就跟我们当时在 reducer 部分所做的一样。如果你还没有了解action creator的话, 去看看相关章节吧~ (./action-creators.js).
5959import * as actionCreators from './action-creators'
6060
6161class Home extends React . Component {
6262 onTimeButtonClick ( delay ) {
63- // This button handler will dispatch an action in response to a click event from a user.
64- // We use here the dispatch function "automatically" provided by connect in a prop.
65- // There are alternative ways to call actionCreators that are already bound to dispatch and those
66- // imply providing the second parameter to 'connect':
63+ // 这个按钮处理器在用户的点击事件后会分发一个 action。
64+ // 我们在这里会使用一个 Connect 提供的分发函数,
65+ // 也有很多其他的调用被绑定到分发器的 actionCreator 的方式,
66+ // 这种方式提供了第二个 Connect 的参数:
6767 // https://github.com/rackt/react-redux/blob/v4.0.0/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options
68- // The "delay" value given to actionCreators.getTime is a delay to simulate an async work being done before we
69- // are able to get the current time. Try to change this value to verify that the delay correctly impacts our UI.
68+ // 被传到 actionCreators.getTime 的 delay 值是为了在我们能得到当前时间之前模拟异步的工作,
69+ // 试着修改这个值来正确影响我们的 UI
7070 this . props . dispatch ( actionCreators . getTime ( delay ) )
7171 }
7272 render ( ) {
73-
74- // Thanks to "connect", we're able to get specific selected data, through the props.
73+
74+ // 因为 Connect 我们能够通过 props 取到特定的数据
7575 var { frozen, time, reduxState } = this . props
7676 var attrs = { }
77- const DELAY = 500 // in ms
77+ const DELAY = 500 // 毫秒
7878
7979 if ( frozen ) {
8080 attrs = {
@@ -94,7 +94,7 @@ class Home extends React.Component {
9494 Try to change this value (in < b > src/home.jsx - line 95</ b > ) to verify that the delay given correctly impacts our UI.
9595 </ i >
9696 < br />
97- { /* We register our button "onClick" handler here: */ }
97+ { /* 我们在这里定义我们的点击处理器 */ }
9898 < button { ...attrs } onClick = { ( ) => this . onTimeButtonClick ( DELAY ) } > Get time!</ button >
9999 < pre >
100100 redux state = { JSON . stringify ( reduxState , null , 2 ) }
@@ -104,13 +104,13 @@ class Home extends React.Component {
104104 }
105105}
106106
107- // 这是我们的select函数 , 它会把我们需要在属性(prop)中对我们的组件暴露的数据从state中抽离出来
107+ // 这是我们的 select 函数 , 它会把我们需要在属性 (prop) 中对我们的组件暴露的数据从 state 中抽离出来
108108const mapStateToProps = ( state /*, props*/ ) => {
109109 return {
110110 frozen : state . _time . frozen ,
111111 time : state . _time . time ,
112- // It is very bad practice to provide the full state like that (reduxState: state) and it is only done here
113- // for you to see its stringified version in our page. More about that here :
112+ // 像 (reduxState: state) 这样提供整个 state 是一种不好的实现,
113+ // 我们在这里这样写是为了让大家能看到我们页面字符串化的结果。更多信息请访问以下链接 :
114114 // https://github.com/rackt/react-redux/blob/v4.0.0/docs/api.md#inject-dispatch-and-every-field-in-the-global-state
115115 reduxState : state ,
116116 }
@@ -120,27 +120,27 @@ const ConnectedHome = connect(mapStateToProps)(Home)
120120
121121export default ConnectedHome
122122
123- // You might have noticed that thanks to redux, while we have a dynamic component that requires some state (to keep
124- // the current time), this state is by no mean present inside the component. Our component only receives props with
125- // needed data.
126- // What we have here is called a stateless component. You should always try to have more stateless components (presented
127- // above as dumb components) in your applications than stateful ones because they are much more reusable.
128- // As suggested in "onTimeButtonClick" handler, we could even go further by passing our click callback as a prop
129- // via "connect" second parameter "mapDispatchToProps". Doing so, we would extract our button behavior outside of
130- // our component, making it even more reusable by allowing for a different click behavior.
131- // Reusability might seem like a fancy overused concept but what having a reusable component also means, is that it's
132- // one component that can be very easily tested (because you can then inject in your component whatever data and
133- // test handlers you want and easily ensure its correct behavior).
123+ // 也许你会发现因为 Redux 让我们可以拥有需要一些状态 (比如保存当前时间) 的动态组件,
124+ // 而这个状态并不在组件当中存在,
125+ // 我们的组件只会接受含有需要的数据的 prop。
126+ // 我们现在拥有了一个无状态组件 ( stateless component), 相比较有状态的组件,
127+ // 我们在编码中应该尽可能更多的使用无状态组件, 因为它们更易于被复用。
128+ // 正如在 "onTimeButtonClick" 处理器中建议的一样, 我们甚至可以把点击的回调函数作为一个 prop
129+ // 从 Connect 的第二个参数 "mapDispatchToProps" 中传入。这么做的话, 我们就可以在组件之外获得按钮的行为,
130+ // 通过允许另一种点击行为让我们更易于重用这个按钮。
131+ // 可复用性的概念也许看起来被过度强调了, 但是拥有一个可复用的组件通常也意味着
132+ // 这个组件能够很简单的被测试 (因为你可以将任何你想要的数据和处理器插入你的组件中,
133+ // 从而很简单的保证它的正确运行)
134134
135- // Before going to ./12_final-words.js, read this side-note about an alternative way to use "connect" HOC...
135+ // 在去看 ./12_final-words.js 之前, 请仔细看以下另一种使用 Connect HOC 的方法。
136136
137- // Because connect(...) returns a function that accept a class and returns another class, you can use it as
138- // an ES7 decorator if you want to. Decorators are an experimental ES7 features that make it possible to annotate
139- // and modify classes and properties at design time (https://github.com/wycats/javascript-decorators).
137+ // 因为 Connect 返回了一个接受一个 class 并返回另一个 class 的函数,
138+ // 我们可以用它作为 ES7 的 decorator。Decorator 是一种 ES7 的实验新特性,
139+ // 让我们能够在设计的时候注释和修改 class 和属性 (https://github.com/wycats/javascript-decorators).
140140
141- // This feature being experimental, it is subject to change and breakage. This means that by using it today, you must be
142- // fully aware of and accept the uncertainty regarding its evolution. Decorators provide syntax sugar to write the
143- // code above slightly differently. Instead of writing :
141+ // 作为一个试验中的特性, 也许会有变化或问题。
142+ // 如果你选择从现在开始使用的话, 请注意和接受今后的不确定性。
143+ // Decorator 提供了一些代码的语法糖让我们的代码变得稍稍不同。原来的这种写法 :
144144
145145/*
146146 class MyClass {}
@@ -170,10 +170,10 @@ export default ConnectedHome
170170 export default class MyClass {}
171171*/
172172
173- // As you can see the application of the HOC function on the component class is now made implicit ( @connect(mapStateToProps) )
174- // instead of calling it ourselves ( @connect(mapStateToProps)(Myclass) ). Some find this approach more elegant, others
175- // dislike the fact that it's hiding what is really happening and many just don't get how decorators works. Knowing all that
176- // and remembering that decorators are still experimental, you can now decide by youselves which "connect" usage you
177- // prefer and you won't be suprised to find both syntax in the many articles, tutorials, starter kits, etc. out there.
173+ // 正如我们看到的, 高层组件的函数现在被作为隐函数使用 ( @connect(mapStateToProps) )
174+ // 而不是直接调用它们自身 ( @connect(mapStateToProps)(Myclass) )。 有些人觉得这种写法更加优雅,
175+ // 而另一些则因为这种写法隐藏了实际发生的事情会当人无法理解 decorator 是如何工作的。
176+ // 知道了这些并了解到 decorator 现在仍在实验阶段的话, 你就可以决定你偏好使用哪一种 Connect 的形式,
177+ // 也不会因为在其他文章, 教学和新手包中看到两种语法而感到惊讶了
178178
179- // Go to ./12_final-words.js for our last advice about what to do now...
179+ // 去 ./12_final-words.js 可以看到我们最后的一些建议
0 commit comments