发布时间:2024-09-11 15:01
博主主页👉🏻蜡笔雏田学代码
今天学习一下使用redux如何实现多组件共享数据
感兴趣的小伙伴一起来看看吧~🤞
我们之前学习的都是只有一个组件获取redux里的数据,也就是Count求和这个组件。但是redux在真实的使用场景中,肯定是有多个组件共享数据,才会使用redux进行状态管理。接下来使用多个组件通过redux实现数据共享。
我们创建一个Person组件,Person组件的数据也交给redux管理,这样Count组件和Person组件就可以实现数据共享。
在redux文件夹下新创建两个文件夹actions和reducers。
注意:Count组件的相关内容在前几篇文章中详细介绍了,此文就不再赘述了…
请阅读👉🏻:Redux求和案例详解版教程
1️⃣首先准备好一个Person组件:
src/containers/Person/index.jsx:
import React, { Component } from 'react'
import { nanoid } from 'nanoid'
export default class Person extends Component {
addPerson = () => {
const name = this.nameNode.value
const age = this.ageNode.value
const personObj = { id: nanoid(), name, age }
console.log(personObj)
}
render() {
return (
<div>
<h2>我是Person组件</h2>
<input ref={c => this.nameNode = c} type="text" placeholder='输入名字' />
<input ref={c => this.ageNode = c} type="text" placeholder='输入年龄' />
<button onClick={this.addPerson}>添加</button>
<ul>
<li>名字1--年龄1</li>
<li>名字2--年龄2</li>
<li>名字3--年龄3</li>
</ul>
</div>
)
}
}
2️⃣在constant.js文件里添加一个类型:
constant.js:
export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'
+ export const ADD_PERSON = 'add_person'
3️⃣编写Person组件的action文件,用于创建action动作对象以供Person组件使用
/src/redux/actions/person.js:
import { ADD_PERSON } from '../constant'
// 创建增加一个人的action动作对象
export const createAddPersonAction = personObj => ({ type: ADD_PERSON, data: personObj })
4️⃣编写Person组件的reducer文件,用于创建一个为Person组件服务的reducer函数
/src/redux/reducers/person.js:
import { ADD_PERSON } from '../constant'
//初始化人的列表
const initState = [{ id: '001', name: 'tom', age: 18 }]
export default function personReducer(preState = initState, action) {
const { type, data } = action
switch (type) {
case ADD_PERSON: //若是添加一个人
return [data, ...preState]
default:
return preState
}
}
此处的personReducer函数是一个纯函数
纯函数:
一类特别的函数: 只要是同样的输入(实参),必定得到同样的输出(返回)。一个函数的返回结果只依赖其参数
,并且执行过程中没有副作用。
必须遵守以下一些约束:
不得改写参数数据
function demo(a){
a=9
}
不会产生任何副作用,例如不能发送网络请求,输入和输出设备
不能调用Date.now()或者Math.random()等不纯的方法
redux的reducer函数必须是一个纯函数
下面是错误写法:
const initState = [{ id: '001', name: 'tom', age: 18 }]
export default function personReducer(preState = initState, action) {
const { type, data } = action
switch (type) {
case ADD_PERSON: //若是添加一个人
//此处不可以这样写,这样会导致preState被改写了,
//personReducer就不是纯函数了,
//会影响redux不能够识别状态的改变。
preState.unshift(data)
return preState
default:
return preState
}
}
5️⃣由于store.js中只引入了为Count组件服务的reducer,没有引入为Person组件服务的reducer,所以Person组件里的reducer根本没有运行,能为store效力的只有CountReducer。
若想要redux为多个组件服务,redux中存放了多个组件的状态,就需要
用一个对象
去存储redux中所有组件的状态,每一个组件存放在redux中的状态都是一组key: value。例如: Count组件: count: 0 ,Person组件: persons: []
合并reducer:
需要引入一个API: combineReducers函数
/src/redux/store.js
/*
该文件专门用于暴露一个store对象,整个应用只有一个store对象
*/
// 引入createStore,专门用于创建redux中最为核心的store对象
import { legacy_createStore as createStore, applyMiddleware, combineReducers } from 'redux';
// 引入为Count组件服务的reducer
import countReducer from './reducers/count'
// 引入为Person组件服务的reducer
import personReducer from './reducers/person'
// 引入redux-thunk,用于支持异步任务
import thunk from 'redux-thunk'
// 汇总所有的reducer变为一个总的reducer
// combineReducers调用时传入的对象就是redux帮我们保存的总的状态对象
const allReducer = combineReducers({
count: countReducer,
persons: personReducer
})
// 暴露store
export default createStore(allReducer, applyMiddleware(thunk))
将原先的countReducer与新引入的personReducer合并,并且将合并后的allReducer传递给createStore函数作为第一个参数,目的是将这两个组件的状态用一个对象包裹起来,再传给store。
6️⃣Person组件里的状态已经存放在了redux中了,现在需要使用react-redux在Person组件里写Person的UI组件以及Person组件的容器组件。
src/containers/Person/index.jsx:
import React, { Component } from 'react'
import { nanoid } from 'nanoid'
import { connect } from 'react-redux'
import { createAddPersonAction } from '../../redux/actions/person'
class Person extends Component {
addPerson = () => {
const name = this.nameNode.value
const age = this.ageNode.value
const personObj = { id: nanoid(), name, age }
this.props.dispatchAddPerson(personObj)
this.nameNode.value = ''
this.ageNode.value = ''
}
render() {
return (
<div>
<h2>我是Person组件</h2>
<input ref={c => this.nameNode = c} type="text" placeholder='输入名字' />
<input ref={c => this.ageNode = c} type="text" placeholder='输入年龄' />
<button onClick={this.addPerson}>添加</button>
<ul>
{
this.props.personArr.map((p) => {
return <li key={p.id}>{p.name}--{p.age}</li>
})
}
</ul>
</div>
)
}
}
export default connect(
// 映射状态
state => ({ personArr: state.persons }),
// 映射操作状态的方法
{ dispatchAddPerson: createAddPersonAction }
)(Person)
7️⃣若要实现Count组件获取Person组件的状态,Person组件获取Count组件的状态
...
<h2>我是Person组件,上方组件求和为:{this.props.count}</h2>
...
export default connect(
// 映射状态
state => ({
personArr: state.persons,
count: state.count
}),
// 映射操作状态的方法
{ dispatchAddPerson: createAddPersonAction }
)(Person)
...
<h2>我是Count组件,下方组件总人数为:{this.props.person}</h2>
...
export default connect(
state => ({
count: state.count,
person: state.persons.length
}),
{
jia: createIncrementAction,
jian: createDecrementAction,
jiaAsync: createIncrementAsyncAction
}
)(Count)
1️⃣定义一个Person组件,和Count组件通过redux共享数据。
2️⃣为Person组件编写:reducer、action,配置constant常量。
3️⃣重点:Person的reducer和Count的Reducer要使用combineReducers进行合并。
合并后的总状态是一个对象!!!
4️⃣交给store的是总reducer,最后注意在组件中取出状态的时候,记得“取到位”。
今天的分享就到这里啦✨ \\textcolor{red}{今天的分享就到这里啦✨} 今天的分享就到这里啦✨
原创不易,还希望各位大佬支持一下 \\textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下
🤞 点赞,你的认可是我创作的动力! \\textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!
⭐️ 收藏,你的青睐是我努力的方向! \\textcolor{green}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!
✏️ 评论,你的意见是我进步的财富! \\textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!