在使用 React 编写组件的时候,我们常常会碰到两个不同的组件之间需要共享状态情况,而通常的做法就是提升状态到父组件。但是这样做会有一个问题,就是尽管只有两个组件需要这个状态,但是因为把状态提到了父组件,那么在状态变化的时候,父组件以及其下面的所有子组件都会重新 render,如果你的父组件比较复杂,包含了其他很多子组件的话,就有可能引起性能问题。

Redux 通过把状态放在全局的 store 里,然后组件去订阅各自需要的状态,当状态发生变化的时候,只有那些订阅的状态发生变化的组件才重新 render,这样就避免了上面说的提升状态所带来的副作用。但是,当我们在写一个 React 组件库的时候,redux 加 react-redux 的组合可能就有点太重了。所以我们可以自己写一个简单的 store,来实现类似 Redux 的订阅模式。

参考 Redux 的实现来写一个简版的 createStore:

function createStore(initialState) {let state = initialState;const listeners = [];function setState(partial) {state = {...state,...partial,};for (let i = 0; i < listeners.length; i++) {listeners[i]();}}function getState() {return state;}function subscribe(listener) {listeners.push(listener);return function unsubscribe() {const index = listeners.indexOf(listener);listeners.splice(index, 1);};}return {setState,getState,subscribe,};
}

我们的 createStore 非常简单,算上空行也只有 33 行,总共暴露了 3 个方法,没有 Redux 里的 dispatch 和 reducer,直接通过 setState 方法改变状态。下面我们来用它一个计数器的例子(在线例子)。

class Counter extends React.Component {constructor(props) {super(props);// 初始化 storethis.store = createStore({count: 0,});}render() {return (<div><Buttons store={store} /><Result store={store} /></div>)}
}class Buttons extends React.Component {handleClick = (step) => () => {const { store } = this.props;const { count } = store.getState();store.setState({ count: count + step });}render() {return (<div><button onClick={this.handleClick(1)}>+</button><button onClick={this.handleClick(1)}>-</button></div>);}
}class Result extends React.Component {constructor(props) {super(props);this.state = {count: props.store.getState().count,};}componentDidMount() {this.props.store.subscribe(() => {const { count } = this.props.store.getState();if (count !== this.state.count) {this.setState({ count });}});}render() {return (<div>{this.state.count}</div>);};
}

例子中 Buttons 里通过 store.setState 来改变 store 中的状态,并不会引起整个 Counter 的重新 render,但是因为 Result 中订阅了 store 的变化,所以当 count 有变化的时候就可以通过改变自己组件内的状态来重新 render,这样就巧妙地避免了不必须要的 render。

最后,上面的 createStore 虽然只有几十行代码,我还是把它写成了一个叫 mini-store 库放在 GitHub 上,并且提供了类似 Redux 的 Provider 和 connect 方法,总共加起来也就 100 多行代码。如果你也在写 React 组件库,需要管理一个复杂组件的状态,不妨试试这个优化方式。

使用 store 来优化 React 组件相关推荐

  1. 使用react实现select_使用 Hooks 优化 React 组件

    奇技指南 本文内容主要是我之前分享的文字版,若想看重点的话可以看之前的Slide: https://ppt.baomitu.com/d/75fc979a 本文作者奇舞团前端开发工程师李喆明. 需求描述 ...

  2. react 组件遍历】_从 Context 源码实现谈 React 性能优化

    (给前端大全加星标,提升前端技能) 转自:魔术师卡颂 学完这篇文章,你会收获: 了解Context的实现原理 源码层面掌握React组件的render时机,从而写出高性能的React组件 源码层面了解 ...

  3. React组件设计实践总结05 - 状态管理

    今天是 520,这是本系列最后一篇文章,主要涵盖 React 状态管理的相关方案. 前几篇文章在掘金首发基本石沉大海, 没什么阅读量. 可能是文章篇幅太长了?掘金值太低了? 还是错别字太多了? 后面静 ...

  4. 不挂载 组件渲染_让你的 React 组件性能跑得再快一点「实践」

    作者:天泽 转发链接:https://www.zoo.team/article/react-render 性能和渲染(Render)正相关 React 基于虚拟 DOM 和高效 Diff 算法的完美配 ...

  5. react组件设计原则_React组件设计规则

    react的目的是将前端页面组件化,用状态机的思维模式去控制组件.组件和组件之间肯定是有关系得,通过合理得组件设计,给每一个组件划定合适得边界,可以有效降低当我们对页面进行重构时对其他组件之间得影响. ...

  6. React组件复用的方式

    React组件复用的方式 现前端的工程化越发重要,虽然使用Ctrl+C与Ctrl+V同样能够完成需求,但是一旦面临修改那就是一项庞大的任务,于是减少代码的拷贝,增加封装复用能力,实现可维护.可复用的代 ...

  7. 基于 Mui 封装常用 React 组件

    基于 Mui 封装常用 React 组件 Mui(MaterialUI) Mui 是基于google的Materia设计风格开发的基于React框架的 UI 框架,之前的名称为MaterialUI. ...

  8. 编写react组件_React组件的“黄金法则”如何帮助您编写更好的代码

    编写react组件 以及钩子如何发挥作用 (And how hooks come into play) Recently I've adopted a new philosophy that chan ...

  9. 【React组件】写一个模仿蓝湖的图片查看器

    前言 最近公司让写一个可以自由拖拽放大的图片查看器,我寻思这还不简单,一顿操作猛如虎,俩小时后: 事实证明,一旦涉及到 DOM 的变换操作,如果很多细节考虑不全,抓过来就写,那基本就凉了.于是我仔细分 ...

最新文章

  1. IJCAI 2020灭霸式拒稿,AI审稿是否更公平?
  2. html百度转到顶部 fixed,科技常识:完美解决安卓端百度浏览器屏蔽fixed悬浮元素的问题...
  3. ffmpeg 移植到 android 并使用
  4. php curl异步跳转,php curl批处理--可控并发异步
  5. 防止QQ密码被盗的五个绝招
  6. POJ3197(连分数表示)
  7. C++ STL 容器 vector
  8. 第3课 攀天梯(ladder)--记忆化搜索(python3实现)
  9. android 游戏引擎 排行_4月旗舰手机性能排行榜:小米10 Pro第四,OPPO Ace2第五
  10. NumPy 基础知识·翻译完成
  11. Word2003和2007如何隐藏去掉回车符
  12. SVN客户端安装及使用
  13. 【计算机组成原理】:计算机系统的组成和层次
  14. 服务器怎么设置mqtt遗嘱消息,MQTT 遗嘱消息、Retained消息、QOS上线下线实现
  15. 如何Deactivate .Net Reflector
  16. 假如你有超能力,会复活哪部经典美剧?
  17. 深入讨论Python中的序列切片语法
  18. 019动物识别检测网页版
  19. 用python写一个有AI的斗地主游戏(二)——简述后端代码和思路
  20. 找不到模块“xxx.vue”或其相应的类型声明。ts

热门文章

  1. FacetWP 筛选与多条件搜索 WordPress插件
  2. php 缩略图增加水印,PHP生成缩略图加图片水印代码
  3. 百度爬虫页面自动繁殖程序+教程自动SEO优化
  4. 浅谈C# Socket编程及C#如何使用多线程
  5. vs2008 调试js
  6. Node.js:一个路由2次 request
  7. 使用 position: sticky 达到粘性元素区域悬浮效果
  8. Oracle客户端安装
  9. 跑深度学习在Linux服务器上常用操作(ssh, screen, tensorboard, jupyter-notebook)
  10. LeetCode 561. Array Partition I