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 有一个好的认识只差一步: 如何从 store 中的 state 读取, 和以及如何派发 actions?
54
6- // Both of these questions can be answered using a single react-redux's binding: connect.
5+ // 这两个问题可以用 react-redux 的 connect 绑定一并解决。
76
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.
7+ // 如我们之前解释的, 当使用 Provider 组件的时候, 我们允许应用中所有组件访问 Redux。
8+ // 但这个访问只能通过没有配备说明文档的功能 "React 的 context" 来完成。
9+ // 为了避开这如"黑魔法"般的 React API , React-Redux 暴露了一个函数, 这样你就能在组件的 类中使用它。
1210
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.
11+ // 我们讨论的这个函数就是 "connect" , 它能让我们用 Redux 的 store 字面值与组件连接上。
12+ // 这样一来, 它就能让你 store 中的 dispatch 函数通过组件的 props 传递,
13+ // 而且可以添加任何你想暴露的属性, 这些暴露的属性将作为你 store 中 state 的一部分。
1614
17- // Using "connect", you'll turn a dumb component into a smart component with very little code overhead
18- // ( https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0).
15+ // 使用 "connect", 能仅用很少的代码将一个笨拙组件 ( dumb component) 转换成一个智能组件 ( smart component)
16+ // 参见: https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0
1917
2018// "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 :
19+ // the actual component class you want to connect.
20+ // 这样一个函数(指 "connect") 被称之为高阶组件 (HOC, Higher Order Component)。
21+ // 高阶组件(译者注: 原文为 Higher Order functions, 可能写错了)来源于"函数设计模式", 这种设计可以在不使用继承的情况下向其添加功能与行为 (component, store, ...)
22+ // 这种方式有利于构造继承, 而且也是开发 React 应用的优先方法(但不是仅限的方法)。
23+ // 下面有更多关于高阶组件 (HOC) 与构造的文章 :
2624// - https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750#.lpp7we7mx
2725// - http://natpryce.com/articles/000814.html
2826
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 :
27+ // 高阶函数 "connect" 旨在解决所有, 从最简单到最复杂的使用情况。
28+ // 在本例中, 我们不会用 " connect" 做很复杂的事,
29+ // 但你可以去下面链接看看完整的 " connect" API 文档 :
3230// https://github.com/rackt/react-redux/blob/v4.0.0/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options
3331
34- // Here is the complete ' connect' signature :
32+ // 这有个 " connect" 的完整用法 :
3533// connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
36- // and here is how you're supposed to use it :
34+ // 这还有个你应该如何使用它 :
3735/*
3836 const wrappedComponentClass = connect(...)(ComponentClass)
3937*/
4038
41- // We will only focus here on the first ' connect' parameter : mapStateToProps...
39+ // 我们只关注这里 " connect" 的第一个参数 : mapStateToProps...
4240
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).
41+ // "connect" 接收了一个参数, 该参数是个函数, 它用于将你想要暴露给组件的数据片段从 state 中选取出来。
42+ // 该函数逻辑上称之为 "selector", 它接收2个参数: 你 store 中的 state, 和当前组件的 props。
43+ // 如下面所示, 我们将该函数命名为 "mapStateToProps"。
44+ // 这个语义化的命名, 只是为了清晰表达该函数是用于: 将 state 映射(或解释为提取)到一些组件的 props 中。
45+ // 组件的 props 还作为参数来提供, 就像通常从基于 state 中的 props 中提取数据片段一样,
46+ // 例如: state.items[props.someID]。
47+
48+ // "mapStateToProps" 应该返回你想要暴露给组件的 props (一般通过一个字面量对象)。
49+ // 这取决于在返回 state 时, 先转换接收到的 state。
50+ // 你可以看看下面 "connect" 的最简单用法(就在组件类的定义之后)。
5451
5552import React from 'react'
5653import { 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).
54+ // 我们用 ES6 的 import 写法来获取所有的 action creator, 如同我们在 reducers 中那样。
55+ // 如果你还没看过我们的 action creator, 转到 ./action-creators.js 去看看。
5956import * as actionCreators from './action-creators'
6057
6158class Home extends React . Component {
6259 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':
67- // 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.
60+ // 当用户点击这个按钮的时候, 该句柄会派发一个action来响应。
61+ // 这里我们使用的 dispatch 函数由 props 中的 connect "自动"提供。
62+ // 还有多种其他的方法来调用已经绑定到 dispatch 中的 actionCreator, 这意味着可以向 "connect" 提供第二个参数:
63+ // https://github.com/rackt/react-redux/blob/v4.0.0/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options
64+ // "delay" 的值传递给 actionCreators.getTime, 用于在获取当前时间之前模拟一次成功的异步操作。
65+ // 尝试修改 delay 的值, 验证延迟是否正确影响了我们的 UI。
7066 this . props . dispatch ( actionCreators . getTime ( delay ) )
7167 }
7268 render ( ) {
7369
74- // Thanks to "connect", we're able to get specific selected data, through the props.
70+ // 要感谢 "connect", 我们能够通过 props 来获取已选择的具体的数据
7571 var { frozen, time, reduxState } = this . props
7672 var attrs = { }
77- const DELAY = 500 // in ms
73+ const DELAY = 500 // 单位: 毫秒
7874
7975 if ( frozen ) {
8076 attrs = {
@@ -94,7 +90,7 @@ class Home extends React.Component {
9490 Try to change this value (in < b > src/home.jsx - line 95</ b > ) to verify that the delay given correctly impacts our UI.
9591 </ i >
9692 < br />
97- { /* We register our button "onClick" handler here : */ }
93+ { /* 这里注册按钮的 "onClick" 句柄 : */ }
9894 < button { ...attrs } onClick = { ( ) => this . onTimeButtonClick ( DELAY ) } > Get time!</ button >
9995 < pre >
10096 redux state = { JSON . stringify ( reduxState , null , 2 ) }
@@ -104,14 +100,13 @@ class Home extends React.Component {
104100 }
105101}
106102
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.
103+ // 这个函数中, 我们将想通过 props 暴露给组件的数据片段从 state 中提取出来。
109104const mapStateToProps = ( state /*, props*/ ) => {
110105 return {
111106 frozen : state . _time . frozen ,
112107 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 :
108+ // 像下面这样 (reduxState: state) 将整个 state 都提供出去不太好,
109+ // 这里这样写只是给你看一下, 更多相关请见 :
115110 // https://github.com/rackt/react-redux/blob/v4.0.0/docs/api.md#inject-dispatch-and-every-field-in-the-global-state
116111 reduxState : state ,
117112 }
@@ -121,34 +116,33 @@ const ConnectedHome = connect(mapStateToProps)(Home)
121116
122117export default ConnectedHome
123118
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).
119+ // 你也许注意到了, 正是要感谢 Redux, 在 state(当前时间下) 的驱动下我们有了动态的组件,
120+ // 该 state 在组件中并不扮演任何角色,
121+ // 我们的组件仅仅只接收 props 中需要的数据。
122+ // 这种组件称之为无状态的组件。在应用程序中你应该总是开发无状态的组件(如之前见过的的笨拙组件)。
123+ // 因为无状态组件具有更高的复用性。
124+ // 就像 "onTimeButtonClick" 句柄中建议的, 将点击回调通过 "connect" 的第二个参数 "mapDispatchToProps" 传递的时候, 我们可以做更多事情。
125+ // 如此这般, 我们就可以将按钮的行为提取出来, 通过替换不同的点击动作, 使之有更高的复用性。
126+ // 复用性似乎成了一个花哨且过度使用的概念, 但是可复用组件意味着, 它可以被很容易的测试, 因为你可以注入任何数据, 然后检查它是否处理正常, 确保它行为正确。
135127
136- // Before going to ./12_final-words.js, read this side-note about an alternative way to use "connect" HOC ...
128+ // 在转到 ./12_final-words.js 之前, 请先阅读一下这个旁注: 如何使用 "connect" 连接高阶组件的另外一种方法 ...
137129
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).
130+ // 因为 connect(...) 返回2个东西: 接收一个类(class) 的函数, 和另外一个类(class),
131+ // 如果你愿意的话, 可以使用 ES7 的修饰器(Decorator) 方法来写。
132+ // 修饰器(Decorator) 是 ES7 中的实验性功能, 它使我们能在设计类与属性时对其进行修改,
133+ // 更多请见: https://github.com/wycats/javascript-decorators
141134
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:
135+ // 该功能是实验性的, 它受制于语言标准的变化。
136+ // 这意味着, 如果你使用了它, 你必须当心和接受标准演进所带来的不确定性。
137+ // 修饰器提供了一个语法糖, 用它编码会和上面的代码有些小区别。
138+ // 以前这样写:
145139
146140/*
147141 class MyClass {}
148142 export default somedecorator(MyClass)
149143*/
150144
151- // You can write :
145+ // 现在这样写 :
152146
153147/*
154148 @somedecorator
0 commit comments