react-redux是基于redux javascript轻量级框架,为了更好的和react结合对redux提供了一些封装,一种更科学的代码组织方式,让我们更舒服地在React的代码中使用Redux。
react-redux很简单他就提供了两个模块:Provider和connect。
Provider
Provider是一个普通组件,可以作为顶层app的分发点,它只需要store属性就可以了。它会将state分发给所有被connect的组件,不管它在哪里,被嵌套多少层。
这个模块是作为整个App的容器,在你原有的App Container的基础上再包上一层,它的工作很简单,就是接受Redux的store作为props,并将其声明为context的属性之一,子组件可以在声明了contextTypes之后可以方便的通过this.context.store访问到store。不过我们的组件通常不需要这么做,将store放在context里,是为了给下面的connect用的。
1
2
3
4
5
6ReactDOM.render(
<Provider store={store}>
<MyRootComponent />
</Provider>,
rootEl
)
如下是Provider组件的核心代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14export default class Provider extends Component {
//在context设置store,可以被子组件引用
getChildContext() {
return { store: this.store }
}
constructor(props, context) {
super(props, context)
this.store = props.store
}
render() {
return Children.only(this.props.children)
}
}
connect
connect是真正的重点,它是一个柯里化函数,意思是先接受两个参数(数据绑定mapStateToProps和事件绑定mapDispatchToProps),再接受一个参数(将要绑定的组件本身):
mapStateToProps:构建好Redux系统的时候,它会被自动初始化,但是你的React组件并不知道它的存在,因此你需要分拣出你需要的Redux状态,所以你需要绑定一个函数,它的参数是state,简单返回你关心的几个值。
mapDispatchToProps:声明好的action作为回调,也可以被注入到组件里,就是通过这个函数,它的参数是dispatch,通过redux的辅助方法bindActionCreator绑定所有action以及参数的dispatch,就可以作为属性在组件里面作为函数简单使用了,不需要手动dispatch。这个mapDispatchToProps是可选的,如果不传这个参数redux会简单把dispatch作为属性注入给组件,可以手动当做store.dispatch使用。这也是为什么要柯里化的原因。
在connect函数中其实是对我们的组件进行了一层包装,在connect中获取到Provider组件在context属性中设置的store。然后在componentDidMount函数中订阅handleChange事件,在handleChange函数中获取了store.getState()并且重新设置了最新的状态this.setState({ storeState }),这样组件状态发生了修改,组件将重新被渲染。
如下是connect组件的核心代码:
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
35export default function connect(mapStateToProps, mapDispatchToProps, mergeProps, options = {}) {
return function wrapWithConnect(WrappedComponent) {
class Connect extends Component {
constructor(props, context) {
super(props, context)
this.store = props.store || context.store
}
trySubscribe() {
if (shouldSubscribe && !this.unsubscribe) {
this.unsubscribe = this.store.subscribe(this.handleChange.bind(this))
this.handleChange()
}
}
componentDidMount() {
this.trySubscribe()
}
handleChange() {
const storeState = this.store.getState()
this.setState({ storeState })
}
render() {
if (withRef) {
this.renderedElement = createElement(WrappedComponent, {
...this.mergedProps,
ref: 'wrappedInstance'
})
} else {
this.renderedElement = createElement(WrappedComponent,this.mergedProps)
}
return this.renderedElement
}
}
}
做好以上流程Redux和React就可以工作了。简单地说就是:
1.顶层分发状态,让React组件被动地渲染。
2.监听事件,事件有权利回到所有状态顶层影响状态。