一、什么是react-redux?
- react-redux是react的一个插件库,这点和redux不一样,react-redux是专门用来简化react中使用redux
二、react-redux原理图
三、react-Redux将所有组件分成两大类
- UI组件:
- 只负责 UI 的呈现,不带有任何业务逻辑
- 通过props接收数据(一般数据和函数)
- 不使用任何 Redux 的 API
- 一般保存在components文件夹下
- 容器组件
- 负责管理数据和业务逻辑,不负责UI的呈现
- 使用 Redux 的 API
- 一般保存在containers文件夹下
四、创建容器组件
- connect(mapStateToProps,mapDispatchToProps)(UI组件)
mapStateToProps:映射状态,返回值是一个对象
mapDispatchToProps:映射操作状态的方法,返回值是一个对象
import {connect} from 'react-redux'
import CountUI from '../../components/Count'
import {incrementAction,decrementAction,incrementAsyncAction} from '../../redux/count_action'
function mapStateToProps(state) {
return {count: state}
}
function mapDispatchToprops(dispatch) {
return {
increment: number => dispatch(incrementAction(number)),
decrement: number => dispatch(decrementAction(number)),
incrementAsync: (number,time) => dispatch(incrementAsyncAction(number,time))
}
}
export default connect(mapStateToProps,mapDispatchToprops)(CountUI)
- APP.js中不再引入Count组件,改成引入Count容器
import React, { Component } from 'react'
import Count from './containers/Count'
import store from './redux/store'
export default class App extends Component {
render() {
return (
<div>
//这里实现了原理图中的左右部分连接,
//Count作为Count组件的容器,而store则相当于原理图右边的内容
<Count store={store}/>
</div>
)
}
}
五、优化
- 在前面,由于组件和容器分别进行定义,则导致文件过多,因此可以将容器和组件合并成一个文件
- 对于容器中的mapStateToProps和mapDispatchToProps还可以进行简写
- 使用了react-redux后,不用再单独对redux中状态的变化进行监测,该步骤可以省略
- 之前在APP.js中使用
<Count store={store}/>
这样的形式传递store,但是当有多个组件都需要进行此步骤的操作时,就过于繁琐,react-redux中可以进行改写,只需在一个地方进行传入即可 - containers/Count/index.jsx
import {connect} from 'react-redux'
import {incrementAction,decrementAction,incrementAsyncAction} from '../../redux/count_action'
import React, { Component } from 'react'
class Count extends Component {
increment = () => {
const {value} = this.selectNode
this.props.increment(value*1)
}
decrement = () => {
const {value} = this.selectNode
this.props.decrement(value*1)
}
oddIncrement = () => {
const {value} = this.selectNode
if(this.props.count % 2 !== 0) {
this.props.increment(value*1)
}
}
asyncIncrement = () => {
const {value} = this.selectNode
this.props.incrementAction(value*1,500)
}
render() {
return (
<div>
<h3>当前求和为:{this.props.count}</h3>
<select ref={c => this.selectNode=c}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button onClick={this.increment}>+</button>
<button onClick={this.decrement}>-</button>
<button onClick={this.oddIncrement}>当前求和为奇数时加</button>
<button onClick={this.asyncIncrement}>异步加</button>
</div>
)
}
}
export default connect(
state => ({count: state}),//映射状态
{
increment: incrementAction,
decrement: decrementAction,
incrementAction: incrementAsyncAction
}//映射操作状态的方法
)(Count)
App.js
import React, { Component } from 'react'
import Count from './containers/Count'
export default class App extends Component {
render() {
return (
<div>
<Count/>
</div>
)
}
}
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App'
import {Provider} from 'react-redux'
import store from './redux/store'
//无需自己给容器组件传递store,
//给<App/>包裹一个<Provider store={store}>即可
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root'))
- 注意:当项目中的reducer过多时,可以将这些reducer一次性整合到一个文件中(redux中新建index.js文件)进行整合,再统一暴露
六、总结
- 容器组件和UI组件整合一个文件
- 无需自己给容器组件传递store,给
<App/>包裹一个<Provider store={store}>
即可。 - 使用了react-redux后也不用再自己检测redux中状态的改变了,容器组件可以自动完成这个工作
- mapDispatchToProps也可以简单的写成一个对象
- 一个组件要和redux“打交道”要经过哪几步?
(1).定义好UI组件---不暴露
(2).引入connect生成一个容器组件,并暴露,写法如下:
connect(
state => ({key:value}), //映射状态
{key:xxxxxAction} //映射操作状态的方法
)(UI组件)
(4).在UI组件中通过this.props.xxxxxxx读取和操作状态