使用 react-redux 绑定GitHub 上提供了针对多个流行框架的 Redux 绑定,包括 React、Angular 和 Vue。这些绑定使得将 Redux 与通过这些框架构建的应用程序相集成变得很容易。
Redux 中不包含 react-redux 绑定,所以您必须使用以下命令单独安装它们:npm install react-redux
绑定提供了一个 API,该 API 包含一个 React 组件和一个 JavaScript 方法:
- Provider 组件允许 Provider 组件中包含的组件访问 Redux 存储。
- void connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options]) 函数将一个 React 表示组件连接到 Redux 存储。
Provider 组件很方便,您不需要在整个组件分层结构中手动传递存储作为一个属性。嵌套在 Provider 组件内的组件会自动获得 Redux 存储的访问权。
connect() 函数将一个表示组件连接到 Redux 存储,以便在存储更改时更新该组件。
与 Redux 存储的自动连接在 中,了解了如何将单个 React 组件连接到 Redux 存储。这种风格非常流行,以至于 redux-react 绑定提供了一个 connect() 方法来自动将无状态功能组件连接到存储。
在本文的整篇文章中,stoplight 都与交通信号灯 同义。
为了演示,我首先将修改 的交通信号灯应用程序的 App 组件,让其使用称为容器组件 的组件 — 这类组件会自动连接到 Redux 存储,并向一个封闭的无状态功能组件提供属性。清单 1 给出了更新后的 App 组件。
清单 1. 应用程序 (app.js),其中现在使用了容器组件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| import React, { Component } from 'react';
import { StoplightContainer } from './stoplight-container';
import { ButtonContainer } from './button-container';
import { createStore } from 'redux';
import { reducer } from './reducer';
export class App extends Component {
render() {
const store = createStore(reducer);
return(
<div>
<StoplightContainer store={store}/>
<ButtonContainer store={store}/>
</div>
)
}
}
|
没有像原始实现中一样返回包含 Stoplight 和 Buttons 组件的 DIV,App 组件的经过改良的 render() 方法返回了一个包含两个容器组件的 DIV:StoplightContainer 和 ButtonContainer。
请注意,我仍将 Redux 存储传递给了 App 组件中包含的组件。您会在下一节看到如何规避该需求。
清单 2 显示了 stoplight 容器。
清单 2. stoplight 容器 (stoplight-container.js)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| import { connect } from 'react-redux';
import { Stoplight } from './stoplight';
const mapStateToProps = state => {
return {
goColor: state == 'GO' ? 'rgb(39,232,51)' : 'white',
cautionColor: state == 'CAUTION' ? 'yellow' : 'white',
stopColor: state == 'STOP' ? 'red' : 'white'
}
}
const mapDispatchToProps = null;
export const StoplightContainer = connect(
mapStateToProps,
mapDispatchToProps
)(Stoplight);
|
简单来讲,StoplightContainer 连接到 Redux 存储,并将应用程序状态映射到它包含的 stoplight 的属性。应用程序状态为 GO、CAUTION 或 STOP,stoplight 的属性为 goColor、cautionColor 和 stopColor。
默认情况下,stoplight 的 3 个属性中的每一个都是 white。当状态为 GO 时,stoplight 容器会将 stoplight 的 goColor 属性映射到绿灯(编码为 rgb(39,232,51))。当状态为 CAUTION 时,会将 cautionColor 映射到 yellow。当状态为 STOP,会将 stopColor 映射到 red。
为了将应用程序状态映射到 stoplight 属性, 使用了 react-redux 绑定的 connect() 函数将 StoplightContainer 连接到 Redux 存储。
通过调用 connect() 函数并将 Stoplight 传递给 connect() 返回的函数,Redux 在 Redux 存储中的状态发生更改时自动更新 Stoplight。您只需调用 connect() 即可实现此目的。当存储发生更改时,Redux 会调用 StoplightContainer 的 mapStateToProps() 方法。Redux 将 StoplightContainer.mapStateToProps() 返回的对象的属性值复制到 StoplightContainer 中包含的 stoplight。
connect() 方法接受两个参数,这两个参数都是函数。第一个函数将来自 Redux 存储的状态映射到所包含的组件(在本例中为 Stoplight)的属性。第二个函数将 Redux 分派调用映射到属性;但是,stoplight 不启用任何行为,所以 stoplight 容器不会将分派调用映射到属性。结果,stoplight 容器的 mapDispatchToProps 函数为 null。
清单 3 显示了 Stoplight 组件的经过再次改良的实现,其中使用了它的 3 个属性作为 SVG 圆圈的 fill 属性。
清单 3. 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
| import React, { Component } from 'react';
export const Stoplight = ({
goColor,
cautionColor,
stopColor
}) => {
return(
<div style={{textAlign: 'center'}}>
<svg height='170'>
<circle cx='145' cy='60' r='15'
fill={stopColor}
stroke='black'/>
<circle cx='145' cy='100' r='15'
fill={cautionColor}
stroke='black'/>
<circle cx='145' cy='140' r='15'
fill={goColor}
stroke='black'/>
</svg>
</div>
)
}
|
Stoplight 组件已恢复为无状态功能组件,它从 StoplightContainer 组件接收自己的属性。
清单 4 显示了 ButtonContainer 组件。
清单 4. 按钮容器 (button-container.js)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| import { connect } from 'react-redux';
import { Buttons } from './buttons';
import { goAction, cautionAction, stopAction } from './actions';
const mapStateToProps = state => {
return {
lightStatus: state
}
}
const mapDispatchToProps = dispatch => {
return {
go: () => { dispatch(goAction) },
caution: () => { dispatch(cautionAction) },
stop: () => { dispatch(stopAction) }
}
}
export const ButtonContainer = connect(
mapStateToProps,
mapDispatchToProps
)(Buttons);
|
ButtonContainer 组件将当前状态映射到一个名为 lightStatus 的 Buttons 属性。信号灯状态就是状态的值(GO、CAUTION 或 STOP)。 |