【Redux】如何实现多组件数据共享

发布时间: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函数是一个纯函数
纯函数:

  1. 一类特别的函数: 只要是同样的输入(实参),必定得到同样的输出(返回)。一个函数的返回结果只依赖其参数,并且执行过程中没有副作用。

  2. 必须遵守以下一些约束:

    • 不得改写参数数据

      function demo(a){
        a=9 
      }
      
    • 不会产生任何副作用,例如不能发送网络请求,输入和输出设备

    • 不能调用Date.now()或者Math.random()等不纯的方法

  3. 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组件编写:reduceraction配置constant常量

3️⃣重点:Person的reducer和Count的Reducer要使用combineReducers进行合并合并后的总状态是一个对象!!!

4️⃣交给store的是总reducer,最后注意在组件中取出状态的时候,记得“取到位”。

今天的分享就到这里啦✨ \\textcolor{red}{今天的分享就到这里啦✨} 今天的分享就到这里啦

原创不易,还希望各位大佬支持一下 \\textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下

🤞 点赞,你的认可是我创作的动力! \\textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!

⭐️ 收藏,你的青睐是我努力的方向! \\textcolor{green}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!

✏️ 评论,你的意见是我进步的财富! \\textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号