
React(九)- React数据共享和Redux案例最终完善
而两个组件之间,则通过Redux来进行数据共享。
安装服务器:
页面能够正常显示:
此时这种运行处于发布模式:
发布日期:2021-05-07 14:50:26
浏览次数:20
分类:技术文章
本文共 7784 字,大约阅读时间需要 25 分钟。
React(九)- React数据共享和Redux案例最终完善
前言
本篇文章是紧接着来讲解。上一篇文章中可以发现,案例都是以单组件为基础,那么接下来来看看如何利用Redux来实现多个组件之间的数据共享。
一. React数据共享
需求:写两个组件,每个组件能够实时的获得另一个组件的状态值,如图:

1.1 案例:多组件之间数据共享
项目结构:

Count
组件(整合UI和容器组件): import React, { Component } from 'react';// 引入connect用来连接UI组件和reduximport { connect } from 'react-redux'import { createIncrementAction, createDecrementAction, createIncrementAsyncAction} from '../../redux/actions/count'class Count extends Component { 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() { return (); }}export default connect( // 此时要根据store文件中,对应的key来决定,因为我们有两个UI组件 // 因此在原本的基础上,我们在store文件中利用combineReducers将多个reducer进行了合并 // 返回的是一个对象,那么每个reducer都是以key,value的形式来存在,因此需要通过state.key来获得对应的状态 state => ({ count: state.he, renshu: state.rens.length }), { jia: createIncrementAction, jian: createDecrementAction, jiaAsync: createIncrementAsyncAction, })(Count)我是Count组件,发现Person组件中的总人数为:{ this.props.renshu}
当前求和为:{ this.props.count}
Person
组件(整合UI和容器组件):
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.jiaYiRen(personObj) } render() { return () }}export default connect( state => ({ yiduiren: state.rens, he: state.he }), { jiaYiRen: createAddPersonAction }// 映射操作状态的方法)(Person)我是Person组件,发现Count组件中的和为{ this.props.he}
this.nameNode = c} /> this.ageNode = c} />{ this.props.yiduiren.map(p => { return
- { p.name}---{ p.age}
}) }
store.js
组件:
/** * 改文件专门用来暴露一个store对象,整个应用只有一个store对象 */// 引入createStore,专门用于创建redux中最为核心的store对象// combineReducers可以将多个reducer进行合并import { applyMiddleware, createStore, combineReducers } from 'redux'// 引入为Count组件服务的reducerimport countReducer from './reducers/count'import personReducer from './reducers/person'import thunk from 'redux-thunk'// 合并所有的reducer,因为createStore()方法只有俩参数。const allReducer = combineReducers({ he: countReducer, rens: personReducer,})// 暴露storeexport default createStore(allReducer, applyMiddleware(thunk))
常量文件constant.js
:
/** * 用于action对象中type类型的常量值 */ export const INCREMENT ='increment' export const DECREMENT ='decrement' export const ADD_PERSON ='addPerson'
App组件:
import React, { Component } from 'react';import Count from './containers/Count'import Person from './containers/Person'class App extends Component { render() { return (); }}export default App;
入口文件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'ReactDOM.render(, document.getElementById('root'))
Action文件:
Action_Count.js
文件:(项目中的文件名称为count.js
,在actions
目录下)
/** * 改文件专门为Count组件生成action对象*/import { INCREMENT, DECREMENT } from '../constant'export const createIncrementAction = data => ({ type: INCREMENT, data })export const createDecrementAction = data => ({ type: DECREMENT, data })// 异步action就是指action的值为函数,异步action中一般会调用同步的action,// 需要npm install redux-thunk ,并配置在store中// 创建action的函数不再返回一般对象,而是一个函数,该函数中写一个异步任务// 异步任务有结果后,分发一个同步的action去真正操作数据export const createIncrementAsyncAction = (data, time) => { return (dispatch) => { setTimeout(() => { dispatch(createIncrementAction(data)) }, time); }}
Action_Person.js
文件:(项目中的文件名称为person.js
,在actions
目录下)
import { ADD_PERSON } from '../constant'// 创建增加一个人的action动作对象export const createAddPersonAction = personObj => ({ type: ADD_PERSON, data: personObj })
Reducer文件:
Reducer_Count.js
文件:(项目中的文件名称为count.js
,在reducers
目录下)
/** * 1.该文件是用来创建一个为Count组件服务的Reducer,Reducer的本质就是一个函数 * 2.reducer函数会接收到两个参数,分别是:之前的状态preState,动作对象action */ import { INCREMENT, DECREMENT } from '../constant' export default function countReducer(preState, action) { if (preState === undefined) preState = 0 /** * 1.type:标识属性,值为字符串,唯一,必要属性。 2.data:数据属性,值类型任意,可选属性。 */ const { type, data } = action // 根据type来决定如何加工数据 switch (type) { case INCREMENT: // 如果是加 return preState + data case DECREMENT: // 如果是减 return preState - data default: return preState }}
Reducer_Person.js
文件:(项目中的文件名称为person.js
,在reducers
目录下)
import { ADD_PERSON } from '../constant'const initState = [{ id: '01', 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 }}
对于多个组件之间的数据共享问题,我们可以发现:
- 多个
reducer
在store.js
文件中都需要被暴露,但是createStore()
方法只能暴露一个reducer
,因此需要通过combineReducers()
来合并reducer
,并且每个reducer
都需要为其定义一个key
。 - 而合并之后的总状态是一个对象,而不再是一个单一的值。☆
- 在组件中取出状态的时候,记得要根据对应的
key
来获取对应的状态。
1.2 纯函数
纯函数是一类特别的函数,只要是同样的输入(实参),必定得到同样的输出返回,同时必须遵守以下几点约束:
- 不得改写参数数据。
- 不会产生任何副作用,例如网络请求,输入和输出设备。
- 不能调用
Date.now()
或者Math.random()
等不纯的方法。 - 而redux的
reducer
函数必须是一个纯函数。
因此,以下这种写法是错误的!:
Person(Reducer):
import { ADD_PERSON } from '../constant'const initState = [{ id: '01', name: 'tom', age: 18 }]export default function personReducer(preState = initState, action) { const { type, data } = action switch (type) { case ADD_PERSON: // 不可以这么写,因为会导致preState被改写,那么personReducer就不是纯函数了。 // preState.unshift(data) // return preState return [data, ...preState] default: return preState }}
二. Redux案例最终版
将store.js
文件中,合并多个reducer
的操作单独提出来,在reducers
目录下创建一个index.js
文件:

/** * 该文件用于汇总所有的reducer */import { combineReducers } from 'redux'import countReducer from './count'import personReducer from './person'export default combineReducers({ he: countReducer, rens: personReducer,})
那么store.js
文件中更改为:
/** * 改文件专门用来暴露一个store对象,整个应用只有一个store对象 */// 引入createStore,专门用于创建redux中最为核心的store对象// combineReducers可以将多个reducer进行合并import { applyMiddleware, createStore } from 'redux'// 引入为Count组件服务的reducerimport thunk from 'redux-thunk'// 只要是index为名字的文件,就可以省略不写import reducer from './reducers'// 暴露storeexport default createStore(reducer, applyMiddleware(thunk))
2.1 项目打包运行
打包命令如下:
npm run build
运行后,会生成一个build
文件:里面包含了你这个项目中所用到的样式、Js等文件。

npm i serve -g
启动命令:(在当前文件夹中)
serve build
执行效果如下:



发表评论
最新留言
哈哈,博客排版真的漂亮呢~
[***.90.31.176]2025年04月14日 09时39分27秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Spring 与使用STOMP消息
2019-03-04
Java Swing JList:列表框组件
2019-03-04
AngularJS $q
2019-03-04
jQuery中的动画
2019-03-04
Linux host命令
2019-03-04
MongoDB 查询分析
2019-03-04
编写Makefile.am
2019-03-04
狂神说MySQL01:初识MySQL
2019-03-04
5.3.2 等待一段时间:编写延时循环
2019-03-04
1.2.3 项目、项目集、项目组合以及运营管理之间的关系
2019-03-04
光环和你一起迎接改版
2019-03-04
1.12 项目和运营的区别
2019-03-04
2.1 组织运行环境
2019-03-04
7.3 制定预算
2019-03-04
习惯养成记打卡-第7章 项目成本管理
2019-03-04
习惯养成记打卡-第9章 项目资源管理
2019-03-04
LeetCode - 98. 验证二叉搜索树(迭代、递归)2
2019-03-04
【△重点△】LeetCode - 4. 寻找两个正序数组的中位数——二分查找
2019-03-04
LeetCode - 5. 最长回文子串——字符串、动态规划
2019-03-04