React-Redux 将所有组件分成两大类:UI 组件和容器组件。
使用React-Redux后,UI 组件只负责 UI 的呈现,不带有任何业务逻辑,UI组件内部不再操作state(状态值,如果不使用React-Redux,则我们需要用state来保存值),所有的界面渲染所用参数都是通过this.props来获取。
负责管理数据和业务逻辑,不负责 UI 的呈现,有业务逻辑,并且使用Redux提供的API。
React-Redux提供了connect方法,用于从 UI 组件生成容器组件。connect的意思,就是将React UI组件与 Redux store 连接起来,生成一个新容器组件。后续我们真正使用的是这个容器组件。
connect([mapStateToProps], [mapDispatchToProps], [mergeProps],[options])
connect方法可以省略mapStateToProps参数,那样的话,UI 组件就不会订阅Store,就是说 Store 的更新不会引起 UI 组件的更新。
mapStateToProps:
这个参数允许我们将 store 中的数据映射为 props 输入给UI组件。该参数可以是一个返回对象的函数,也可以就是一个对象。key为UI界面对应的名称,value为state处理的结果。
如果是函数,则该函数参数的原型为:
mapStateToProps(state, ownProps) : stateProps
建立一个从(外部的)state对象到(UI 组件的)props对象的映射关系。如果作为函数实参,mapStateToProps执行后应该返回一个对象,里面的每一个键值对就是一个映射。
mapStateToProps会订阅 Store,每当state更新的时候,就会自动执行,重新计算 UI 组件的参数,从而触发 UI 组件的重新渲染。
mapStateToProps的第一个参数总是state对象,还可以使用第二个参数,代表调用时传入给容器组件的props对象的一个属性。使用ownProps作为参数后,如果容器组件的参数发生变化,也会引发 UI 组件重新渲染。
下面以具体实例来说明:
示例:
const mapStateToProps = (state) => {
// UI组件中需要什么参数,对象中就写哪些参数
return {
value: state.count,
uname: state.username
}
}
mapDispatchToProps:
mapDispatchToProps是connect函数的第二个参数,用来建立 UI 组件的参数到store.dispatch方法的映射。也就是说,它定义了哪些用户的操作应该当作 Action,传给 Store。它可以是一个函数,也可以是一个对象。
它的作用是,将 action 映射为 props 输入给UI组件。触发action更新reducer,进而更新state,从而驱动参数1变化,引起UI数据的变化。
1、作为函数
原型说明:
mapDispatchToProps(dispatch, ownProps): dispatchProps
如果mapDispatchToProps是一个函数,需要dispatch和ownProps(容器组件的props对象)两个参数。作为函数,应该返回一个对象,该对象的每个键值对都是一个映射,定义了 UI 组件的参数怎样发出 Action。
dispach(action) : React-Redux是传入的一个函数,用于分派(发送)消息。
示例:
const mapDispatchToProps = (dispatch, ownProps) => {
return {
onIncreaseClick: () => dispatch({type: 'increase'}),
onReduceClick: () => dispatch({type: 'reduce'})
}
}
connect通过mapStateToProps 与 mapDispatchToProps 这个两参数的自动调用方式,将UI和业务逻辑分开,UI组件仅仅通过props来控制渲染,没有任何业务逻辑,容器组件负责逻辑业务。
import React, {Component} from 'react'
import {connect} from "react-redux";
import { createStore } from 'redux';
const reducer = (state = { count: 0, count1: 0 }, action) => {
switch (action.type) {
case 'INCREASE':
return {
//状态是只读的,但是现在的操作模式是直接修改状态
count: state.count + 1,
};
case 'DECREASE':
return {
count: state.count - 1,
};
default:
return state;
}
};
const store = createStore(reducer);
class App extends Component {
render() {
const {value, name, onIncreaseClick, onReduceClick} = this.props
return (
{name}
{value}
);
}
}
const mapStateToProps = (state) => {
return {
value: state.count,
uname: state.username
}
}
const mapDispatchToProps = (dispatch, ownProps) => {
return {
onIncreaseClick: () => dispatch({type: 'INCREASE'}),
onReduceClick: () => dispatch({type: 'DECREASE'})
}
}
//生成一个 容器组件
const MyContainer = connect(mapStateToProps, mapDispatchToProps)(App);
export default MyContainer;
2.作为对象:
调用这个方法后,内部会自动调用 dispatch 方法。
// mapDispatchToProps 对象写法,
const mapDispatchToProps = {
sendAction: () => {
return {
type: 'send_action',
list: xxxxx
}
}
}
connect之所以会成功,是因为Provider组件:
1. 在原应组件上包裹层,使原来整个应成为Provider的组件
2. 接收Redux的store作为props,通过context对象传递给孙组件上的connect
connect连接 Redux 和 React UI组件,Provider包在我们的容器组件的外层,容器组件接收上一级 Provider 提供的 store 中的 state 和 dispatch,传给一个内部构造函数,返回一个对象,以属性形式传给我们的容器组件。
引用组件示例
import {Provider} from "react-redux";
import MyApp from './mycoontainer';