结合使用 Redux 和 React现在您已经知道了如何在没有框架的情况下使用 Redux,已为学习如何将它与 React 结合使用做好了准备。
图 3 中所示的交通信号灯应用程序使用与前一个版本相同的状态、缩减程序和操作 — 但在本例中它是一个 React 应用程序。
图 3. 一个交通信号灯
该应用程序表示美国的一处交通信号灯。当信号灯为绿色时,如图 3 中顶部图片中所示,唯一可能的下一个状态是 Caution,所以 Go 和 Stop 按钮被禁用。当信号灯为黄色时,唯一可能的下一个状态是 Stop。当信号灯为红色时,唯一可能的下一个状态是 Go。
应用程序缩减程序和它的操作的代码未更改,但现在分别位于自己的文件中。清单 4 给出了应用程序的入口点的代码。
清单 4. 入口点 (index.js)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| import React from 'react';
import ReactDOM from 'react-dom';
import Redux, { createStore } from 'redux';
import { reducer } from './reducer';
import { App } from './app';
const store = createStore(reducer);
const render = () => (
ReactDOM.render(<App store={store}/>,
document.getElementById('example'))
)
store.subscribe(render);
render(); // initial render
|
清单 4 的代码使用 ECMAScript 6 (ES6) 导入函数来导入 React、ReactDOM、Redux 和 Redux createStore() 函数。
当应用程序启动时,它使用应用程序的缩减程序创建一个 Redux 存储(如 所示)。接下来,应用程序使用 Redux 存储的 subscribe() 方法订阅该存储。当 Redux 存储中的状态更改时,Redux 会调用 render() 函数,该函数将呈现 App 组件。请注意, 中的代码将 Redux 存储设置为一个同名的 App 属性。
清单 5 给出了 App 组件。
清单 5. 应用程序 (app.js)1
2
3
4
5
6
7
8
9
10
11
12
13
14
| import React, { Component } from 'react';
import { Stoplight } from './stoplight';
import { Buttons } from './buttons';
export class App extends Component {
render() {
return(
<div>
<Stoplight store={this.props.store} />
<Buttons store={this.props.store} />
</div>
)
}
}
|
App 组件进而导入和呈现两个其他的组件(Stoplight 和 Buttons),并将 Redux 存储传递给这些子组件。
清单 6 显示了 Stoplight 组件。
清单 6. stoplight (stoplight.js)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| import React, { Component } from 'react';
const stopColor = (state) => {
return state == 'STOP' ? 'red' : 'white';
}
const cautionColor = (state) => {
return state == 'CAUTION' ? 'yellow' : 'white';
}
const goColor = (state) => {
return state == 'GO' ? 'rgb(39,232,51)' : 'white';
}
export const Stoplight = ({
store
}) => {
const state = store.getState();
return(
<div style={{textAlign: 'center'}}>
<svg height='170'>
<circle cx='145' cy='60' r='15'
fill={stopColor(state)}
stroke='black'/>
<circle cx='145' cy='100' r='15'
fill={cautionColor(state)}
stroke='black'/>
<circle cx='145' cy='140' r='15'
fill={goColor(state)}
stroke='black'/>
</svg>
</div>
)
}
|
Stoplight 是一个 React 无状态功能组件,依据应用程序的状态来呈现不同颜色的 SVG 圆圈。该组件从存储的 getState() 方法获取状态,随后使用 3 个帮助器方法之一将状态转换为一种颜色。
通过调用 中 Redux 存储的 subscribe() 方法,React 在 Redux 状态更改时呈现交通信号灯。这些状态更改由应用程序的按钮发起。在清单 7 中(Buttons 组件的代码),可以看到按钮如何发起状态更改。
清单 7. 按钮 (buttons.js)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| import React, { Component } from 'react';
import { goAction, cautionAction, stopAction } from './actions';
export const Buttons = ({
store
}) => {
const state = store.getState();
return(
<div style={{textAlign: 'center'}}>
<button onClick={() => {store.dispatch(goAction)}}
disabled={state == 'GO' || state == 'CAUTION'}
style={{cursor: 'pointer'}}>
Go
</button>
<button onClick={() => {store.dispatch(cautionAction)}}
disabled={state == 'CAUTION' || state == 'STOP'}
style={{cursor: 'pointer'}}>
Caution
</button>
<button onClick={() => {store.dispatch(stopAction)}}
disabled={state == 'STOP' || state == 'GO'}
style={{cursor: 'pointer'}}>
Stop
</button>
</div>
)
}
|
按钮被呈现时,它调用 Redux 存储的 getState() 方法来获取应用程序状态的引用。然后 Buttons 组件使用该状态配置按钮的已禁用状态。
当用户单击按钮时,该按钮的 onClick() 回调会调用 Redux 存储的 dispatch() 方法,并传递一个合适的操作。 |