react-redux和redux是两个不同的概念。
redux是一个重要的数据管理库。redux的作用是帮助处理应用程序中复杂的数据管理和状态管理,它可以让你的应用程序更加可维护和可扩展。
react-redux是一个react库,它可以帮助react开发者在react应用程序中集成redux。它通过提供一组特定于react的API来简化了redux的使用。
使用react-redux,你可以在react组件中直接操作redux中的状态和数据,而无需使用繁琐的API和命令。这样可以使代码更加简洁和易于维护。 总之,react-redux是一个非常有用的库,它可以使react开发者更加轻松地处理复杂的数据管理和状态管理。

根据模型图,改造求和案例
- 步骤1:清除Count组件里面的redux的所有API
import React, { Component } from 'react'
export default class Count extends Component {
increment = () => {
// 普通加
// 1、获取用户选择的值
const { value } = this.selectNumber
}
decrement = () => {
// 普通减
// 1、获取用户选择的值
const { value } = this.selectNumber
}
incrementIfOdd = () => {
// 当前求和为奇数为
// 1、获取用户选择的值
const { value } = this.selectNumber
}
incrementAsync = () => {
// 异步加
// 1、获取用户选择的值
const { value } = this.selectNumber
}
render() {
return (
<div>
<h1>当前求和为:????</h1>
<select ref={(c) => (this.selectNumber = 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.incrementIfOdd}>当前求和为奇数为</button>
<button onClick={this.incrementAsync}>异步加</button>
</div>
)
}
}
- 步骤2:创建Count-UI组件的容器组件
文件:src/containers/Count/index.jsx
// 引入Count的UI组件
import CountUI from '../../components/Count'
// 引入react-redux中的connect用于连接UI组件和容器组件
import { connect } from 'react-redux'
// 创建并暴露一个容器组件
export default connect()(CountUI)
这里我们需要使用react-redux来连接我们的UI组件,所以我们需要安装依赖:
npm i react-redux
现在我们在App.jsx里面将Count的UI组件替换为容器组件
import React, { Component } from 'react'
// import Count from './components/Count'
// 引入Count的容器组件
import Count from './containers/Count'
// 引入store,用于传入容器组件
import store from './redux/store'
export default class App extends Component {
render() {
return (
<div>
<Count store={store}/>
</div>
)
}
}
这里需要将store通过props的方式引入,否则会报错:
Could not find "store" in the context of "Connect(Count)". Either wrap the root component in a <Provider>, or pass a custom React context provider to <Provider> and the corresponding React context consumer to Connect(Count) in connect options.
现在运行我们可以正常看见修改后的页面:

- 步骤3:在容器组件里面传递UI组件状态和操作状态的方法
在这里我们就直接说了,在connect方法第一次执行的时候需要传递两个方法:mapStateToProps和mapDispatchToProps.
mapStateToProps方法是用于传递UI组件状态mapDispatchToProps方法是用于传递UI组件操作状态的方法
文件:src/containers/Count/index.jsx
// 引入Count的UI组件
import CountUI from '../../components/Count'
// 引入action
import {
createIncrementAction,
createDecrementAction,
createIncrementAsyncAction
} from '../../redux/count_action'
// 引入react-redux中的connect用于连接UI组件和容器组件
import { connect } from 'react-redux'
/**
* 1.mapStateToProps函数返回的是一个对象
* 2.返回对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value
* 3.mapStateToProps用于传递状态
* @param {*} state
* @returns
*/
function mapStateToProps (state) {
return {count: state}
}
/**
* 1.mapDispatchToProps函数返回的是一个对象
* 2.返回对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value
* 3.mapDispatchToProps用于传递操作状态的方法
* @param {*} dispatch
* @returns
*/
function mapDispatchToProps (dispatch) {
return {
jia: num => dispatch(createIncrementAction(num)),
jian: num => dispatch(createDecrementAction(num)),
jiaAsync: (num,time) => dispatch(createIncrementAsyncAction(num,time))
}
}
// 创建并暴露一个容器组件
export default connect(mapStateToProps,mapDispatchToProps)(CountUI)
- 步骤4:在UI组件里面使用容器组件传递过来的状态与操作状态的方法
文件:src/components/Count/index.jsx
import React, { Component } from 'react'
export default class Count extends Component {
increment = () => {
// 普通加
// 1、获取用户选择的值
const { value } = this.selectNumber
this.props.jia(value*1)
}
decrement = () => {
// 普通减
// 1、获取用户选择的值
const { value } = this.selectNumber
this.props.jian(value*1)
}
incrementIfOdd = () => {
// 当前求和为奇数为
// 1、获取用户选择的值
const { value } = this.selectNumber
if (this.props.count %2 !== 0) {
this.props.jia(value*1)
}
}
incrementAsync = () => {
// 异步加
// 1、获取用户选择的值
const { value } = this.selectNumber
this.props.jiaAsync(value*1,500)
}
render() {
return (
<div>
<h1>当前求和为:{this.props.count}</h1>
<select ref={(c) => (this.selectNumber = 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.incrementIfOdd}>当前求和为奇数为</button>
<button onClick={this.incrementAsync}>异步加</button>
</div>
)
}
}
- 最后查看效果

- 小节总结
(1). 明确两个概念:
1). UI组件:不能使用任何redux的api,只负责页面的呈现、交互等。
2). 容器组件:负责和redux通信,将结果交给UI组件。
(2). 如何创建一个容器组件——靠react-redux的connect函数
connect(mapStateToProps,mapDispatchToProps)(UI组件)
-mapStateToProps: 映射状态,返回值是一个对象
-mapDispatchToProps: 映射操作状态的方法,返回值是一个对象
(3). 备注1:容器组件中的store是靠props传进去的,而不是在容器组件中直接引入。
(4). 备注2:mapDispatchToProps可以是一个函数,也可以是一个对象。
优化代码
1、优化容器组件
将容器组件的connect函数先使用箭头函数进行优化:
(1). 将普通函数改为箭头函数, src/containers/Count/index.jsx
// 引入Count的UI组件
import CountUI from '../../components/Count'
// 引入action
import {
createIncrementAction,
createDecrementAction,
createIncrementAsyncAction
} from '../../redux/count_action'
// 引入react-redux中的connect用于连接UI组件和容器组件
import { connect } from 'react-redux'
// function mapStateToProps (state) {
// return {count: state}
// }
const mapStateToProps = state => ({count:state})
// function mapDispatchToProps (dispatch) {
// return {
// jia: num => dispatch(createIncrementAction(num)),
// jian: num => dispatch(createDecrementAction(num)),
// jiaAsync: (num,time) => dispatch(createIncrementAsyncAction(num,time))
// }
// }
const mapDispatchToProps = dispatch => ({
jia: num => dispatch(createIncrementAction(num)),
jian: num => dispatch(createDecrementAction(num)),
jiaAsync: (num,time) => dispatch(createIncrementAsyncAction(num,time))
})
// 创建并暴露一个容器组件
export default connect(mapStateToProps,mapDispatchToProps)(CountUI)
(2). 直接将箭头函数体作为connect函数的参数
// 引入Count的UI组件
import CountUI from '../../components/Count'
// 引入action
import {
createIncrementAction,
createDecrementAction,
createIncrementAsyncAction
} from '../../redux/count_action'
// 引入react-redux中的connect用于连接UI组件和容器组件
import { connect } from 'react-redux'
// 创建并暴露一个容器组件
export default connect(
state => ({count: state}),
dispatch => ({
jia: num => dispatch(createIncrementAction(num)),
jian: num => dispatch(createDecrementAction(num)),
jiaAsync: (num,time) => dispatch(createIncrementAsyncAction(num,time))
})
)(CountUI)
(3). 将mapDispacthToProps直接写为一个对象
// 引入Count的UI组件
import CountUI from '../../components/Count'
// 引入action
import {
createIncrementAction,
createDecrementAction,
createIncrementAsyncAction
} from '../../redux/count_action'
// 引入react-redux中的connect用于连接UI组件和容器组件
import { connect } from 'react-redux'
// 创建并暴露一个容器组件
export default connect(
state => ({count: state}),
{
jia:createIncrementAction,
jian:createDecrementAction,
jiaAsync:createIncrementAsyncAction
}
)(CountUI)
这里可以有一点困惑,其实该对象被传递给UI组件使用时,简要的流程是这样的:
UI组件 ===> this.props.jia(value*1) // 但是jia对应的值其实是createIncrementAction这个函数
实际调用 ===> createIncrementAction(value*1) // 这时返回给store的值是一个action对象,而不是函数
最后store监测到值是一个action对象,直接调用reducer修改更新状态的值。
2、关闭redux的监听
原来我们修改redux的状态,需要使用一个API:store.subscribe来监听状态的改变,再次渲染页面,现在使用了react-redux,它已经帮我们做了状态变化的监听,不需要我们自己写了:
关闭在入口文件的监听事件:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
// import store from './redux/store';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// store.subscribe(() => {
// root.render(
// <React.StrictMode>
// <App />
// </React.StrictMode>
// );
// })
3、使用Provider组件优化store对容器组件的传递
原来我们传递给容器组件的方式是在App组件里面通过props的方式将store传递给容器组件的,但是这样有一个问题:
import React, { Component } from 'react'
// 引入Count的容器组件
import Count from './containers/Count'
// 引入store,用于传入容器组件
import store from './redux/store'
export default class App extends Component {
render() {
return (
<div>
{/* 给容器组件传递store */}
<Count store={store} />
<Count1 store={store} />
<Count2 store={store} />
<Count3 store={store} />
<Count4 store={store} />
</div>
)
}
}
假设如上代码,我们有很多个容器组件,难道我们需要一个一个的这样手写props吗?这样很不合理,所以react-redux提供了一个Provider组件帮我们实现了对整个应用的容器组件传递store,无需我们一个一个的props手写传递。
(1). 将原来在APP组件传递store的方式去掉
import React, { Component } from 'react'
// 引入Count的容器组件
import Count from './containers/Count'
export default class App extends Component {
render() {
return (
<div>
<Count/>
</div>
)
}
}
(2). 在入口文件引入并使用Provider组件
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import store from './redux/store'
import { Provider } from 'react-redux'
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
)
至此,无论有多少个容器组件,都无需我们手写props进行传递store了,非常人性化。
4、将容器组件与UI组件整合为一个文件
为了避免文件过多,将容器组件和UI组件合并为一个组件可以使代码更加简洁和易于维护。这样可以将UI组件的状态和属性与容器组件的状态和属性分离,使得组件之间的通信更加明确和紧密。此外,将容器组件和UI组件合并为一个组件也可以减少组件的数量,使得代码结构更加清晰和易于理解。
合并非常简单,就是将UI组件的代码搬到容器组件里面来即可。
// 引入action
import {
createIncrementAction,
createDecrementAction,
createIncrementAsyncAction
} from '../../redux/count_action'
// 引入react-redux中的connect用于连接UI组件和容器组件
import { connect } from 'react-redux'
import React, { Component } from 'react'
class Count extends Component {
increment = () => {
// 普通加
// 1、获取用户选择的值
const { value } = this.selectNumber
this.props.jia(value*1)
}
decrement = () => {
// 普通减
// 1、获取用户选择的值
const { value } = this.selectNumber
this.props.jian(value*1)
}
incrementIfOdd = () => {
// 当前求和为奇数为
// 1、获取用户选择的值
const { value } = this.selectNumber
if (this.props.count %2 !== 0) {
this.props.jia(value*1)
}
}
incrementAsync = () => {
// 异步加
// 1、获取用户选择的值
const { value } = this.selectNumber
this.props.jiaAsync(value*1,500)
}
render() {
return (
<div>
<h1>当前求和为:{this.props.count}</h1>
<select ref={(c) => (this.selectNumber = 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.incrementIfOdd}>当前求和为奇数为</button>
<button onClick={this.incrementAsync}>异步加</button>
</div>
)
}
}
// 创建并暴露一个容器组件
export default connect(
state => ({count: state}),
/*dispatch => ({
jia: num => dispatch(createIncrementAction(num)),
jian: num => dispatch(createDecrementAction(num)),
jiaAsync: (num,time) => dispatch(createIncrementAsyncAction(num,time))
})*/
{
jia:createIncrementAction,
jian:createDecrementAction,
jiaAsync:createIncrementAsyncAction
}
)(Count)
使用的时候,引入容器组件即可。
小节总结
- 优化
connect函数的代码逻辑 - 引入
Provider组件优化容器组件的store传递 - 引入
react-redux后无需自己监测redux的变化 mapDispatchToProps也可以简化写成对象形式- 一个组件要和
redux“打交道”要经过几个步骤:
(1).定义好UI组件——不暴露
(2).引入connect函数生成一个容器组件,并暴露,写法如下:
connect(
state => ({key:value}), // 映射状态
{key:value} // 映射操作状态的方法
)(UI组件)
(3).在UI组件中通过this.props.xxxx读取和操作状态



















