https://github.com/qiqiboy/memo-render
A react-component for optimizing performance when it's parent re-renders.
https://github.com/qiqiboy/memo-render
react react-component react-memo react-performace react-render shouldcomponentupdate
Last synced: 4 months ago
JSON representation
A react-component for optimizing performance when it's parent re-renders.
- Host: GitHub
- URL: https://github.com/qiqiboy/memo-render
- Owner: qiqiboy
- Created: 2020-03-08T02:20:34.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2024-09-26T22:17:16.000Z (over 1 year ago)
- Last Synced: 2025-10-30T13:48:40.210Z (7 months ago)
- Topics: react, react-component, react-memo, react-performace, react-render, shouldcomponentupdate
- Language: JavaScript
- Size: 20.5 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# MemoRender
A react-component for optimizing performance when it's parent re-renders.
`MemoRender`是一个非常简单的 react 组件,它是为了某些追求性能场景下,阻止一些已经声明的组件在本身`props`未发生变化(指深度比较 deep diff 后)时频繁重复渲染。
* [安装](#安装)
* [如何使用](#如何使用)
- [`disabled`](#disabled)
- [`deps`](#deps)
- [`children`](#children)
* [原理](#原理)
* [陷阱](#陷阱)
## 安装
```bash
$ npm install memo-render --save
// yarn
$ yarn add memo-render
```
## 如何使用
`MemoRender`的使用非常简单,它默认情况下,你只需要将它嵌套包裹需要优化的组件节点即可。它会深度对比子节点对象的变化,以决定是否跳过react渲染。
```diff
-
+
+
+
```
### `disabled`
是否启用渲染优化
### `deps`
`deps`是可选的。类似`useMemo` `useCallback`等 hooks 的第二个参数,即需要进行对比的依赖项数组。如果`deps={[]}`,则表示任何情况下都不进行渲染更新。
使用`deps`可以使对比更加高效。
```typescript
...
```
### `children`
需要优化的组件节点
## 原理
频繁的重复渲染是大多数事后导致应用下降的原因,而减少渲染这也正是 react 优化性能的最主要方向:[`Avoid Reconciliation`](https://reactjs.org/docs/optimizing-performance.html#avoid-reconciliation) 。大多数时候,我们应当尽可能的通过优化组件划分、组合逻辑、状态模型等,来避免非必要的组件被迫重复渲染。
但是受限于业务形态或者组件维护、业务逻辑限制等原因,有些组件无法从经常更新的上层组件中抽离。所以这时候就需要适用`shouldComponentUpdate`等优化手段了。`shouldComponentUpdate`仅适用于项目本身的组件,对于第三方组件无法适用该方法优化。
而`MemoRender`就是用于这种优化场景,无需改造原有组件,直接将它放到需要优化的节点上层,即可达到一定的优化效果。这是因为组件传递的各种 props(包括 children),大多都是局部临时变量。对于 object 类型数据,局部临时生成,每次都是新的变量对象,这导致 react 内部的 diffing 比较不一致,持续进入下一层组件的`ceconciliation`阶段,即重复渲染。`MemoRender`正式通过深度比较`children`节点是否有变化来告诉 react 是否跳过本次渲染。
感谢`react-fast-compare`,`MemoRender`借助 react 本身的`react.memo`优化技巧,通过深度比较`children`节点,来告诉 react 是否跳过本次渲染。
## 陷阱
> 我们准备了一篇[《高性能表单指南》](https://github.com/qiqiboy/react-formutil/issues/18),可以了解更多
首先,相信我,绝大多数情况下你都不需要`MemoRender`。
`MemoRender`并不是适用于所有场景,首先第一原则与 `shouldComponentUpdate` / `React.memo` / `React.PureComponent` 的指导思想一致:
**`If the slowdown is noticeable?`**
即,应当仅在应用性能出现明显下降时,再考虑应用这些优化手段。过度优化,可能导致应用存在潜在的 bug(例如组件无法响应 props 或 state 变化的更新)、优化逆反(过度的深度比较可能比 react 本身的 diffing、reconciliation 更慢)等
另外如果`children`节点存在传递了局部内联函数(临时函数),`MemoRender`会无法起到优化作用,甚至起到反作用,导致应用反而更慢。
```typescript
/**
* Bad 错误示例
* 下面两个示例套用MemoRender是无效的,甚至会降低性能
* 因为 onChange 是一个始终变化的函数,而函数是无法深度比较的
* 第二个例子虽然传递的options是一个对象,但是因为其包含临时函数属性onChange,因此也会导致优化失效
*/
function APP() {
return (
{}} />
);
}
```
正确的做法是使用`deps`属性,或者创建不可变的 `onChange` 函数,例如放到组件实例(class 组件)或者适用 memoizeation 优化(function 组件、hooks):
```typescript
/**
* Good 优化后
*/
function APP() {
const onChange = useCallback(() => {}, []);
return (
{}} />
);
}
```