前言
react-redux
不同于redux
,前者的诞生是由于react
出品方认为使用rudux
的react
使用者太多了,进而Facebook公司自己出了react-redux
来更好的优化react
的使用。
使用 react-redux
- 安装
react-redux
yarn add react-redux
- 在
react-redux
中,将组件分为两类:UI组件、容器组件
1. UI组件
1)只负责 UI 的呈现,不带有任何业务逻辑
2)通过props
接收数据(一般数据和函数)
3)不使用任何 Redux
的 API
4)一般保存在components
文件夹下
2. 容器组件
1)负责管理数据和业务逻辑,不负责UI的呈现
2)使用 Redux
的 API
3)一般保存在containers
文件夹下
- 其中,UI组件,不涉及
redux
相关代码,由 容器组件充当桥梁进行沟通,如下:
相关API
- Provider:让所有组件都可以得到state数据
<Provider store={
store}>
<App />
</Provider>
- connect:用于包装 UI 组件生成容器组件
import {
connect } from 'react-redux'
connect(
mapStateToprops,
mapDispatchToProps
)(Counter)
- mapStateToprops:将外部的数据(即state对象)转换为UI组件的标签属性
const mapStateToprops = function (state) {
return {
value: state
}
}
- mapDispatchToProps:将分发action的函数转换为UI组件的标签属性
在redux基本使用的demo基础上,进行修改:
目录结构:
- components\Count\index.jsx(UI组件)
该文件中不再含有和rudux
相关的指令
import React, {
Component } from 'react'
export default class Count extends Component {
state = {
carName:'奔驰c63'}
//加法
increment = ()=>{
const {
value} = this.selectNumber
this.props.jia(value*1)
}
//减法
decrement = ()=>{
const {
value} = this.selectNumber
this.props.jian(value*1)
}
//奇数再加
incrementIfOdd = ()=>{
const {
value} = this.selectNumber
if(this.props.count % 2 !== 0){
this.props.jia(value*1)
}
}
//异步加
incrementAsync = ()=>{
const {
value} = this.selectNumber
this.props.jiaAsync(value*1,500)
}
render() {
//console.log('UI组件接收到的props是',this.props);
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>
)
}
}
- containers\Count\index.jsx(容器组件)
该文件用于书写和redux
相关的桥梁代码
核心函数——从react-redux
中暴露的方法connect
//引入Count的UI组件
import CountUI from '../../components/Count'
//引入action
import {
createIncrementAction,
createDecrementAction,
createIncrementAsyncAction
} from '../../redux/count_action'
//引入connect用于连接UI组件与redux
import {
connect} from 'react-redux'
/*
1.mapStateToProps函数返回的是一个对象;
2.返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value
3.mapStateToProps用于传递状态
*/
function mapStateToProps(state){
return {
count:state}
}
/*
1.mapDispatchToProps函数返回的是一个对象;
2.返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value
3.mapDispatchToProps用于传递操作状态的方法
*/
function mapDispatchToProps(dispatch){
return {
jia:number => dispatch(createIncrementAction(number)),
jian:number => dispatch(createDecrementAction(number)),
jiaAsync:(number,time) => dispatch(createIncrementAsyncAction(number,time)),
}
}
//使用connect()()创建并暴露一个Count的容器组件
export default connect(mapStateToProps,mapDispatchToProps)(CountUI)
- App.jsx
import React, {
Component } from 'react'
import Count from './containers/Count'
import store from './redux/store'
export default class App extends Component {
render() {
return (
<div>
{
/* 给容器组件传递store */}
<Count store={
store} />
</div>
)
}
}
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import store from './redux/store'
ReactDOM.render(<App/>,document.getElementById('root'))
//监测redux中状态的改变,如redux的状态发生了改变,那么重新渲染App组件
store.subscribe(()=>{
ReactDOM.render(<App/>,document.getElementById('root'))
})
注:store.subsrcibe()
方法可以不用在调用了,因为在使用了react-redux
之后,若store
的状态有改变,react-redux
会自动的刷新页面,展示最新数据。
redux
文件夹中的四个文件constant.js
、count_action.js
、count_reducer.js
、store.js
没有改动
使用的优化
使用 Provider
-
在使用 react-redux时,我们需要通过 props 将 store,传递给容器组件
-
但如果容器组件有很多,每个都需要传store,那么对我们来说,会很麻烦
-
因此,使用 Provider,并给 Provider 传递 store,那么 Provider 会自动传递store给所有 容器组件
-
App.js
import React, {
Component } from 'react'
import Count from './containers/Count'
export default class App extends Component {
render() {
return (
<div>
<Count/> {
/* 不需要自己再传递 store */}
</div>
)
}
}
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import store from './redux/store'
import {
Provider} from 'react-redux'
// 借助 Provider 统一传递
ReactDOM.render(
<Provider store={
store}>
<App />
</Provider>
, document.getElementById('root'));
整合UI组件跟容器组件
- 因为UI 组件并不需要我们渲染,而是直接由
react-redux
的connect
方法,生成容器组件 - 所以,我们常常将 UI 组件 跟 容器组件 写成一个 文件,仅暴露容器组件即可,如下:
- 通常 整合后的组件,放在
containers
文件夹 - containers\Count\index.jsx
import React, {
Component } from 'react'
//引入action
import {
createIncrementAction,
createDecrementAction,
createIncrementAsyncAction
} from '../../redux/count_action'
//引入connect用于连接UI组件与redux
import {
connect} from 'react-redux'
//定义UI组件
class Count extends Component {
state = {
carName:'奔驰c63'}
//加法
increment = ()=>{
const {
value} = this.selectNumber
this.props.jia(value*1)
}
//减法
decrement = ()=>{
const {
value} = this.selectNumber
this.props.jian(value*1)
}
//奇数再加
incrementIfOdd = ()=>{
const {
value} = this.selectNumber
if(this.props.count % 2 !== 0){
this.props.jia(value*1)
}
}
//异步加
incrementAsync = ()=>{
const {
value} = this.selectNumber
this.props.jiaAsync(value*1,500)
}
render() {
//console.log('UI组件接收到的props是',this.props);
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>
)
}
}
//使用connect()()创建并暴露一个Count的容器组件
export default connect(
state => ({
count:state}),
//mapDispatchToProps的一般写法
/* dispatch => ({
jia:number => dispatch(createIncrementAction(number)),
jian:number => dispatch(createDecrementAction(number)),
jiaAsync:(number,time) => dispatch(createIncrementAsyncAction(number,time)),
}) */
//mapDispatchToProps的简写
{
jia:createIncrementAction,
jian:createDecrementAction,
jiaAsync:createIncrementAsyncAction,
}
)(Count)
注:此处mapDispatchToProps
的简写并没有调用dispatch
方法,原因是:由于引入了react-redux
,在调用conncet
方法时,他会识别connect(a,b)()
中参数b
是否对应的是action
,若是action
类别,则会自动调用dispatch
方法进行打包,从而简化代码书写。
效果:
转载:https://blog.csdn.net/weixin_45664402/article/details/115829224