React.js 小书 Lesson17 - 前端应用状态管理 —— 状态提升
- 作者:胡子大哈
- 原文链接:http://huziketang.com/books/react/lesson17
- 转载请注明出处,保留原文链接和作者信息。
上一个评论功能的案例中,可能会有些同学会对一个地方感到疑惑: CommentList中显示的评论列表数据为什么要通过父组件 CommentApp 用 props 传进来?为什么不直接存放在 CommentList 的 state 当中?例如这样做也是可以的:
class CommentList extends Component {
constructor () {
this.state = { comments: [] }
}
addComment (comment) {
this.state.comments.push(comment)
this.setState({
comments: this.state.comments
})
}
render() {
return (
<div>
{this.state.comments.map((comment, i) =>
<Comment comment={comment} key={i} />
)}
</div>
)
}
}
如果把这个 comments 放到 CommentList 当中,当有别的组件也依赖这个 comments 数据或者有别的组件会影响这个数据,那么就带来问题了。举一个数据依赖的例子:例如,现在我们有另外一个和 CommentList 同级的 CommentList2 ,也是需要显示同样的评论列表数据。

CommentList2 和 CommentList 并列为 CommentApp 的子组件,它也需要依赖 comments 显示评论列表。但是因为 comments 数据在 CommentList 中,它没办法访问到。
遇到这种情况,我们将这种组件之间共享的状态交给组件最近的公共父节点保管,然后通过 props 把状态传递给子组件,这样就可以在组件之间共享数据了。

在我们的例子当中,如果把 comments 交给父组件 CommentApp ,那么 CommentList 和 CommentList2 都可以通过 props 获取到 comments,React.js 把这种行为叫做“状态提升”。
但是这个 CommentList2 是我们临时加上去的,在实际案例当中并没有涉及到这种组件之间依赖 comments 的情况,为什么还需要把 comments 提升到 CommentApp?那是因为有个组件会影响到 comments ,那就是 CommentInput。CommentInput 产生的新的评论数据是会插入 comments 当中的,所以我们遇到这种情况也会把状态提升到父组件。
总结一下:当某个状态被多个组件依赖或者影响的时候,就把该状态提升到这些组件的最近公共父组件中去管理,用 props 传递数据或者函数来管理这种依赖或着影响的行为。
我们来看看状态提升更多的例子,假设现在我们的父组件 CommentApp 只是属于更大的组件树 PostApp 的一部分:

而这个更大的组件树的另外的子树的 CommentsCount 组件也需要依赖 comments来显示评论数,那我们就只能把 comments 继续提升到这些依赖组件的最近公共父组件 PostApp 当中。
现在继续让我们的例子极端起来。假设现在 PostApp 只是另外一个更大的父组件 Index 的子树。而 Index 的某个子树的有一个按钮组件可以一键清空所有 comments(也就是说,这个按钮组件可以影响到这个数据),我们只能继续 commenets 提升到 Index 当中。
你会发现这种无限制的提升不是一个好的解决方案。一旦发生了提升,你就需要修改原来保存这个状态的组件的代码,也要把整个数据传递路径经过的组件都修改一遍,好让数据能够一层层地传递下去。这样对代码的组织管理维护带来很大的问题。到这里你可以抽象一下问题:
如何更好的管理这种被多个组件所依赖或影响的状态?
你可以看到 React.js 并没有提供好的解决方案来管理这种组件之间的共享状态。在实际项目当中状态提升并不是一个好的解决方案,所以我们后续会引入 Redux 这样的状态管理工具来帮助我们来管理这种共享状态,但是在讲解到 Redux 之前,我们暂时采取状态提升的方式来进行管理。
对于不会被多个组件依赖和影响的状态(例如某种下拉菜单的展开和收起状态),一般来说只需要保存在组件内部即可,不需要做提升或者特殊的管理。
课后练习
因为第三方评论工具有问题,对本章节有任何疑问的朋友可以移步到 React.js 小书的论坛 发帖,我会回答大家的疑问。
React.js 小书 Lesson17 - 前端应用状态管理 —— 状态提升的更多相关文章
- React.js 小书 Lesson2 - 前端组件化(一):从一个简单的例子讲起
作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson2 转载请注明出处,保留原文链接和作者信息. 很多课程一上来就给大家如何配置环境.怎么写 Re ...
- React.js 小书 Lesson3 - 前端组件化(二):优化 DOM 操作
作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson3 转载请注明出处,保留原文链接和作者信息. 看看上一节我们的代码,仔细留意一下 change ...
- React.js 小书 Lesson4 - 前端组件化(三):抽象出公共组件类
作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson4 转载请注明出处,保留原文链接和作者信息. 为了让代码更灵活,可以写更多的组件,我们把这种模 ...
- 【React.js小书】动手实现 React-redux(五):Provider - 方志
我们要把 context 相关的代码从所有业务组件中清除出去,现在的代码里面还有一个地方是被污染的.那就是 src/index.js 里面的 Index: 1234567891011121314151 ...
- React.js 小书介绍
React.js 小书 Github 关于作者 这是一本关于 React.js 的小书. 因为工作中一直在使用 React.js,也一直以来想总结一下自己关于 React.js 的一些知识.经验.于是 ...
- React.js小书总结
(迁移自旧博客2017 08 27) 第一阶段 react的组件相当于MVC里面的View. react.js 将帮助我们将界面分成了各个独立的小块,每一个块就是组件,这些组件之间可以组合.嵌套,就成 ...
- React.js 小书 Lesson16 - 实战分析:评论功能(三)
作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson16 转载请注明出处,保留原文链接和作者信息. 接下来的代码比较顺理成章了.修改 Commen ...
- React.js 小书 Lesson12 - state vs props
作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson12 转载请注明出处,保留原文链接和作者信息. 我们来一个关于 state 和 props 的 ...
- React.js 小书 Lesson5 - React.js 基本环境安装
作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson5 转载请注明出处,保留原文链接和作者信息. 安装 React.js React.js 单独使 ...
随机推荐
- Linux原理与实践
Linux 中的文件及权限 -rwxr-xr-x 1 cat animal 68 03-31 21:47 sleep.sh 三种用户角色: r 4 w 2 x 1 user ,文件的所有者 group ...
- numpy.histogram 官方手册
numpy.histogram numpy.histogram(a, bins=10, range=None, normed=False, weights=None, density=None) Co ...
- uC/OS-II 一些函数简介
获得更多资料欢迎进入我的网站或者 csdn或者博客园 以前搞硬件的经验,最近突然翻出来了.分享给大家:主要讲解uC/OS-II常用函数:虽说现在转行软件了,但是感觉之前搞硬件的经验还真是很有用对于理解 ...
- 190411Python面向对象编程
一.面向对象的概念 类:把一类事物的相同特征抽取出来整合到一起就是一个类,类是一个抽象的概念 对象:基于类创建的一个具体的事物 class People(object): '这是一个人类的类' def ...
- js 定时器的用法和清除
一.设置定时器 window对象提供了两个方法来实现定时器的效果, 分别是window.setTimeout()和window.setInterval.其中前者可以使一段代码在指定时间后运行:而后者则 ...
- 洛谷 P2234 [HNOI2002]营业额统计
题目描述 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是 ...
- FPGA基础学习(5) -- 时序约束(实践篇)
目录 1. 理论回顾 2. 时间裕量 3. 最大延迟和最小延迟 4. 案例分析 参考文献: 距离上一篇有关时序的理论篇已经有一段时间了(可以参考博文FPGA时序约束--理论篇),实际上此段时间,甚至到 ...
- audiosprite的使用
github地址: https://github.com/tonistiigi/audiosprite 使用方法: http://www.jikexueyuan.com/course/2510_2.h ...
- python大作业-图书管理系统
#缺少循环执行和错误处理 #add()函数 添加了循环执行 #错误处理:regist()函数 登录和退出选择的时候添加了错误处理 import sys import importlib importl ...
- LeetCode记录之20——Valid Parentheses
09.18更新算法采用栈的思想解决,方法①所示. 本题主要是找是否有匹配的字符串,因为还没有复习到栈之类的知识点,只能还是采用暴力方法了,后期会补上更加优化的算法.我的思路就是先遍历一遍找是否有匹配的 ...