11// 章节 4 - get-state.js
22
3- // How do we retrieve the state from our Redux instance?
3+ // 如何从 Redux 实例中读取 state ?
44
55import { createStore } from 'redux'
66
@@ -9,22 +9,20 @@ var reducer_0 = function (state, action) {
99}
1010
1111var store_0 = createStore ( reducer_0 )
12- // Output : reducer_0 was called with state undefined and action { type: '@@redux/INIT' }
12+ // 输出 : reducer_0 was called with state undefined and action { type: '@@redux/INIT' }
1313
14- // To get the state that Redux is holding for us, you call getState
14+ // 为了读取 Redux 保存的 state,你可以调用 getState
1515
1616console . log ( 'store_0 state after initialization:' , store_0 . getState ( ) )
17- // Output : store_0 state after initialization: undefined
17+ // 输出 : store_0 state after initialization: undefined
1818
19- // So the state of our application is still undefined after the initialization? Well of course it is,
20- // our reducer is not doing anything... Remember how we described the expected behavior of a reducer in
21- // "about-state-and-meet-redux"?
22- // "A reducer is just a function that receives the current state of your application, the action,
23- // and returns a new state modified (or reduced as they call it)"
24- // Our reducer is not returning anything right now so the state of our application is what
25- // reducer() returns, hence "undefined".
19+ // 都已经初始化过了,难道程序的 state 还是 undefined 的?没错,正是如此,
20+ // 到目前为止,我们的 reducer 还什么事都没做过…… 你是否还有印象,我们在 "about-state-and-meet-redux" 那一章里是怎么描述一个 reducer 的预期行为的?
21+ // “一个 reducer 只是一个函数,它能收到程序当前的 state 与 action,
22+ // 然后返回一个 modify(又或者学别人一样称之为 reduce )过的新 state ”
23+ // 我们的 reducer 目前什么都不返回,所以程序的 state 当然只能是 reducer() 返回的那个叫 “undefined” 的东西。
2624
27- // Let's try to send an initial state of our application if the state given to reducer is undefined:
25+ // 接下来,我们试着在 reducer 收到 undefined 的 state 时,给程序发一个初始状态:
2826
2927var reducer_1 = function ( state , action ) {
3028 console . log ( 'reducer_1 was called with state' , state , 'and action' , action )
@@ -36,14 +34,14 @@ var reducer_1 = function (state, action) {
3634}
3735
3836var store_1 = createStore ( reducer_1 )
39- // Output: reducer_1 was called with state undefined and action { type: '@@redux/INIT' }
37+ // 输出: reducer_1 was called with state undefined and action { type: '@@redux/INIT' }
4038
4139console . log ( 'store_1 state after initialization:' , store_1 . getState ( ) )
42- // Output: store_1 state after initialization: {}
40+ // 输出: store_1 state after initialization: {}
4341
44- // As expected, the state returned by Redux after initialization is now {}
45-
46- // There is however a much cleaner way to implement this pattern thanks to ES6:
42+ // 如我们所愿,现在 Redux 初始化以后返回的 state 变成 {} 了
43+ //
44+ // 感谢ES6,这个模式现在实现起来很清晰:
4745
4846var reducer_2 = function ( state = { } , action ) {
4947 console . log ( 'reducer_2 was called with state' , state , 'and action' , action )
@@ -52,16 +50,16 @@ var reducer_2 = function (state = {}, action) {
5250}
5351
5452var store_2 = createStore ( reducer_2 )
55- // Output : reducer_2 was called with state {} and action { type: '@@redux/INIT' }
53+ // 输出 : reducer_2 was called with state {} and action { type: '@@redux/INIT' }
5654
5755console . log ( 'store_2 state after initialization:' , store_2 . getState ( ) )
58- // Output : store_2 state after initialization: {}
56+ // 输出 : store_2 state after initialization: {}
5957
60- // You've probably noticed that since we've used the default parameter on state parameter of reducer_2,
61- // we no longer get undefined as state's value in our reducer's body.
58+ // 估计你已经发现了,我们给 reducer_2 的 state 参数传了默认值之后,
59+ // reducer 就不会再取到 undefined 的 state 了。
6260
63- // Let's now recall that a reducer is only called in response to an action dispatched and
64- // let's fake a state modification in response to an action type 'SAY_SOMETHING '
61+ // 小结一下:调用 reducer ,只是为了响应一个派发来的 action 。
62+ // 接下来,我们在 response 里模拟一个 state 修改,其响应的 action 类型是 'SAY_SOMETIHG '
6563
6664var reducer_3 = function ( state = { } , action ) {
6765 console . log ( 'reducer_3 was called with state' , state , 'and action' , action )
@@ -78,33 +76,29 @@ var reducer_3 = function (state = {}, action) {
7876}
7977
8078var store_3 = createStore ( reducer_3 )
81- // Output : reducer_3 was called with state {} and action { type: '@@redux/INIT' }
79+ // 输出 : reducer_3 was called with state {} and action { type: '@@redux/INIT' }
8280
8381console . log ( 'store_3 state after initialization:' , store_3 . getState ( ) )
84- // Output: redux state after initialization: {}
85-
86- // Nothing new in our state so far since we did not dispatch any action yet. But there are few
87- // important things to pay attention to in the last example:
88- // 0) I assumed that our action contains a type and a value property. The type property is mostly
89- // a convention in flux actions and the value property could have been anything else.
90- // 1) You'll often see the pattern involving a switch to respond appropriately
91- // to an action received in your reducers
92- // 2) When using a switch, NEVER forget to have a "default: return state" because
93- // if you don't, you'll end up having your reducer return undefined (and lose your state).
94- // 3) Notice how we returned a new state made by merging current state with { message: action.value },
95- // all that thanks to this awesome ES7 notation (Object Spread): { ...state, message: action.value }
96- // 4) Note also that this ES7 Object Spread notation suits our example because it's doing a shallow
97- // copy of { message: action.value } over our state (meaning that first level properties of state
98- // are completely overwritten - as opposed to gracefully merged - by first level property of
99- // { message: action.value }). But if we had a more complex / nested data structure, you might choose
100- // to handle your state's updates very differently:
101- // - using Immutable.js (https://facebook.github.io/immutable-js/)
102- // - using Object.assign (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
103- // - using manual merge
104- // - or whatever other strategy that suits your needs and the structure of your state since
105- // Redux is absolutely NOT opinionated on this (remember, Redux is a state container).
106-
107- // Now that we're starting to handle actions in our reducer let's talk about having multiple reducers and
108- // combining them.
109-
110- // Go to next tutorial: 05_combine-reducers.js
82+ // 输出: redux state after initialization: {}
83+
84+ // 到目前为止,我们都还没有得到一个新 state, 因为我们还没有真的派发过任何 action 。
85+ // 不过在最后一个例子里,有几个点值得注意:
86+ //
87+ // 0) 我假设了 action 里一定包含了一个 type 跟一个 value 。type 基本上是 flux action 已经约定俗成的,
88+ // 而 value 属性可以是任何类型的。
89+ // 1) 这里有个常见模式:在 reducer 里用 switch 来响应对应的 action 。
90+ // 2) 用 switch 的时候, **永远** 不要忘记放个 “default” 来返回 “state”,否则,
91+ // 你的 reducer 可能会返回 “undefined” (等于你的 state 就丢了)
92+ // 3) 注意 { message: action.value } 是怎么被合并到当前 state 来形成新 state 的,
93+ // 这全要感谢牛逼的 ES7 notation (Object Spread): { ...state, message: action.value }
94+ // 4) 还要注意:之所以这个例子能用ES7 Object Spread notation ,是因为它只对 state 里的
95+ // { message: action.value} 做了浅拷贝(也就是说, state 第一个层级的属性直接被 { message: action.value } 覆盖掉了 —— 与之相对,其实也有优雅的合并方式 )
96+ // 但是如果数据结构更复杂或者是嵌套的,那处理state更新的时候,很可能还需要考虑一些完全不同的做法:
97+ // - 可以考虑: Immutable.js (https://facebook.github.io/immutable-js/)
98+ // - 可以考虑: Object.assign (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
99+ // - 可以考虑: 手工合并
100+ // - 又或者考虑用其它任何能满足需要且适合 state 结构的方法,Redex 对此是全无预设的方式的(要记得 Redux 只是个状态的容器)。
101+
102+ // 现在开始,我们要在 reducer 里处理 action 了,我们将会有多个 reducer 并会组合它们。
103+
104+ // 前往下一个章节: 05_combine-reducers.js
0 commit comments