1- // Tutorial 12 - Provider-and-connect.js
1+ // 教程 12 - Provider-and-connect.js
22
3- // Our tutorial is almost over and the only missing piece to leave you with a good overview of Redux is:
4- // How do we read from our store's state and how do we dispatch actions?
3+ // 到这为止我们的教程就基本上结束了, 关于 Redux 唯一剩下的问题
4+ // 就是我们如何能读取 store 里面的 state 以及如何进行action的分发。
55
6- // Both of these questions can be answered using a single react-redux's binding: connect.
6+ // 这两个问题都能够使用 Connect 去解决。
77
8- // As we previously explained, when using the Provider component we allow all components of our app to
9- // access Redux. But this access can only be made through the undocumented feature " React's context". To
10- // avoid asking you to use such a "dark" React API, React-Redux is exposing a function that you can use
11- // on a component class.
8+ // 正如我们前面所讲解的, 当我们使用 Provider 组件时, 我们允许我们应用中的所有组件访问Redux.
9+ // 但是这种访问只能使用不正式的特性 React's context 来实现,
10+ // 为了避免这种"黑科技"式 (不规范) 的 API 调用,
11+ // React-Redux 为我们暴露了一个组件中的函数让我们可以使用。
1212
13- // The function we're talking about is "connect" and it allows to literally connect your component with your Redux's store.
14- // By doing so, it provides your store's dispatch function through a component's prop and also adds any
15- // properties you want to expose as part of your store's state.
13+ // 这个函数就是 Connect , 它让我们可以实现一个组件和 Redux store 的绑定,
14+ // 通过这种绑定可以让store通过组件的属性 (prop) 分发函数,
15+ // 也可以根据我们自己的需要增加任何需要暴露的属性作为store里面state的一部分。
1616
17- // Using "connect ", you'll turn a dumb component into a smart component with very little code overhead
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,14 +104,13 @@ class Home extends React.Component {
104104 }
105105}
106106
107- // This is our select function that will extract from the state the data slice we want to expose
108- // through props to our component.
107+ // 这是我们的 select 函数, 它会把我们需要在属性 (prop) 中对我们的组件暴露的数据从 state 中抽离出来
109108const mapStateToProps = ( state /*, props*/ ) => {
110109 return {
111110 frozen : state . _time . frozen ,
112111 time : state . _time . time ,
113- // It is very bad practice to provide the full state like that (reduxState: state) and it is only done here
114- // for you to see its stringified version in our page. More about that here :
112+ // 像 (reduxState: state) 这样提供整个 state 是一种不好的实现,
113+ // 我们在这里这样写是为了让大家能看到我们页面字符串化的结果。更多信息请访问以下链接 :
115114 // https://github.com/rackt/react-redux/blob/v4.0.0/docs/api.md#inject-dispatch-and-every-field-in-the-global-state
116115 reduxState : state ,
117116 }
@@ -121,60 +120,60 @@ const ConnectedHome = connect(mapStateToProps)(Home)
121120
122121export default ConnectedHome
123122
124- // You might have noticed that thanks to redux, while we have a dynamic component that requires some state (to keep
125- // the current time), this state is by no mean present inside the component. Our component only receives props with
126- // needed data.
127- // What we have here is called a stateless component. You should always try to have more stateless components (presented
128- // above as dumb components) in your applications than stateful ones because they are much more reusable.
129- // As suggested in "onTimeButtonClick" handler, we could even go further by passing our click callback as a prop
130- // via "connect" second parameter "mapDispatchToProps". Doing so, we would extract our button behavior outside of
131- // our component, making it even more reusable by allowing for a different click behavior.
132- // Reusability might seem like a fancy overused concept but what having a reusable component also means, is that it's
133- // one component that can be very easily tested (because you can then inject in your component whatever data and
134- // 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+ // 从而很简单的保证它的正确运行)
135134
136- // 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 的方法。
137136
138- // Because connect(...) returns a function that accept a class and returns another class, you can use it as
139- // an ES7 decorator if you want to. Decorators are an experimental ES7 features that make it possible to annotate
140- // 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).
141140
142- // This feature being experimental, it is subject to change and breakage. This means that by using it today, you must be
143- // fully aware of and accept the uncertainty regarding its evolution. Decorators provide syntax sugar to write the
144- // code above slightly differently. Instead of writing :
141+ // 作为一个试验中的特性, 也许会有变化或问题。
142+ // 如果你选择从现在开始使用的话, 请注意和接受今后的不确定性。
143+ // Decorator 提供了一些代码的语法糖让我们的代码变得稍稍不同。原来的这种写法 :
145144
146145/*
147146 class MyClass {}
148147 export default somedecorator(MyClass)
149148*/
150149
151- // You can write :
150+ // 你可以这么写 :
152151
153152/*
154153 @somedecorator
155154 export default class MyClass {}
156155*/
157156
158- // Applying this syntax to redux connect, you can replace :
157+ // 通过这种特性使用redux connect, 我们可以把如下代码 :
159158
160159/*
161160 let mapStateToProps = (state) => { ... }
162161 class MyClass {}
163162 export default connect(mapStateToProps)(MyClass)
164163*/
165164
166- // by :
165+ // 替换成 :
167166
168167/*
169168 let mapStateToProps = (state) => { ... }
170169 @connect (mapStateToProps)
171170 export default class MyClass {}
172171*/
173172
174- // As you can see the application of the HOC function on the component class is now made implicit ( @connect(mapStateToProps) )
175- // instead of calling it ourselves ( @connect(mapStateToProps)(Myclass) ). Some find this approach more elegant, others
176- // dislike the fact that it's hiding what is really happening and many just don't get how decorators works. Knowing all that
177- // and remembering that decorators are still experimental, you can now decide by youselves which "connect" usage you
178- // 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+ // 也不会因为在其他文章, 教学和新手包中看到两种语法而感到惊讶了
179178
180- // Go to ./12_final-words.js for our last advice about what to do now...
179+ // 去 ./12_final-words.js 可以看到我们最后的一些建议
0 commit comments