资料地址1:https://pan.baidu.com/s/1bmPVGYpNTGlGKUvccQuUzw 提取码:lyx6
资料地址2:https://pan.baidu.com/s/1TtshzgNRObeacfUzOyqxSQ 提取码:9ol1
这篇文章主要为大家介绍了React 18源码深入分析useMemo useCallback memo用法及区别,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪。
最近在做 React 相关的组件搭建,因为涉及到大量的图形计算以及页面渲染,所以特意翻了下性能优化相关的hooks使用,如 useMemo、useCallback 和 memo。在这篇文章中,我们将探讨这些功能的用法和区别,并通过源码分析来理解它们的工作原理,开整!
一、useMemo
useMemo 是一个用于优化性能的 React 钩子。它可以帮助我们避免在组件重新渲染时执行昂贵的计算。useMemo 接受两个参数:一个函数和一个依赖数组。当依赖数组中的值发生变化时,useMemo 会重新计算并返回新的值。否则,它将返回上一次计算的值。
一个简单的例子:
import React, { useMemo } from "react";
function ExpensiveComponent({ a, b }) {
const result = useMemo(() => {
console.log("Expensive calculation...");
return a * b;
}, [a, b]);
return <div>Result: {result}</div>;
}
二、useCallback
useCallback 是另一个用于优化性能的 React 钩子。它可以帮助我们避免在组件重新渲染时创建新的函数实例。useCallback 接受两个参数:一个函数和一个依赖数组。当依赖数组中的值发生变化时,useCallback 会返回一个新的函数实例。否则,它将返回上一次创建的函数实例。
再看一个简单的例子:
import React, { useCallback } from "react";
function ButtonComponent({ onClick, children }) {
return <button onClick={onClick}>{children}</button>;
}
function ParentComponent() {
const handleClick = useCallback(() => {
console.log("Button clicked");
}, []);
return (
<div>
<ButtonComponent onClick={handleClick}>Click me</ButtonComponent>
</div>
);
}
三、reconciler的工作方式
对于同一个节点,比较其ReactElement 与FiberNode,同时生成子FiberNode,根据比较的结果,生成不同的标记(比如说:插入,移动,删除等)
1、比如说需要在页面上挂载<div>foo</div>,这段代码经过jsx("div")转换后,生成ReactElement,然后将ReactElement与当前的FiberNode进行比较,由于是第一次挂载,当前的FiberNode为null,所以比较的结果是生成新的子FiberNode,然后给子FiberNode打上Placement的标记
2、如果说将<div>foo</div> 更新为<p>foo</p>,那么同样这段代码经过jsx("p")转换后,生成ReactElement,然后拿这个ReactElement和p对应的FiberNode(那么此时这个FiberNode就是一个type为div的FiberNode)进行比较,然后生成子fibreNode,将div对应的fiberNode 标记为Deletion,将p对应的fiberNode标记为Placement
3、当所有ReactElement比较完后,会生成一棵fiberNode树,一共会存在两棵fiberNode树:
current:与视图中真实UI对应的fiberNode树
workInProgress:触发更新后,正在reconciler中计算的fiberNode树
四、函数式组件
在react 16.8.0后 (2019年2月6日),推荐函数式编程,用函数定义组件。
新增了Hooks特性,一种无需编写类即可使用状态和其他 React 特性的方法
const App = () => {
return (
<div>
<h1>
这里是函数式组件
</h1>
</div>
)
}
const root = ReactDOM.createRoot(document.querySelector("#root"))
root.render(<App/>)
五、调和器
即便 React DOM 和 React Native 渲染器的区别很大,但也需要共享一些逻辑。特别是协调算法需要尽可能相似,这样可以让声明式渲染,自定义组件,state,生命周期方法和 refs 等特性,保持跨平台工作一致。
为了解决这个问题,不同的渲染器彼此共享一些代码。我们称 React 的这一部分为 “reconciler”。当处理类似于 setState() 这样的更新时,reconciler 会调用树中组件上的 render(),然后决定是否进行挂载,更新或是卸载操作。
Reconciler 没有单独的包,因为他们暂时没有公共 API。相反,它们被如 React DOM 和 React Native 的渲染器排除在外。
有疑问加站长微信联系(非本文作者)