三者都是用于解决父子嵌套,父组件状态变化导致子组件也会做无用的重新渲染问题。
解析
1.子组件不包含状态值(react.memo())
当父组件未给子组件传递任何属性,我们可以通过React.memo()
来控制函数子组件的渲染
- 注意: 当我们传值给子组件时,这时使用
memo()
函数就对控制组件的更新不起作用了
javascript
import { useState } from "react";
import { Child } from "./child";
export const Parent = () => {
const [count, setCount] = useState(0);
const increment = () => setCount(count + 1);
return (
<div>
<button onClick={increment}>点击次数:{count}</button>
<Child />
</div>
);
};
javascript
import {memo} from 'react'
export const Child=memo(()=>{
consloe.log('渲染了')
return <div>子组件</div>
})
//使用memo()包裹后的组件,在Parent组件重新渲染更新时,Child组件将不会
2.父组件向子组件传递了一个函数(useCallback())
如果useCallback第二个参数依赖项没有发生改变,则直接返回缓存结果,不会重新渲染
- 注意: 如果直接使用
useState
解构的setName()
传给子组件, 子组件将不会重复渲染,因为解构出来的是一个memoized 函数。
typescript
import { useCallback, useState } from "react";
import { Child } from "./child";
export const Parent = () => {
const [count, setCount] = useState(0);
const [name, setName] = useState("小明");
const increment = () => setCount(count + 1);
//使用useCallback钩子包裹的回调函数是memoized函数,
//他初次调用该函数时,缓存参数和计算结果,再次调用这个函数时,
//如果第二个参数依赖项没有发生改变,则直接返回缓存结果,不会重新渲染
const onClick = useCallback((name: string) => {
setName(name);
}, []);
return (
<div>
<button onClick={increment}>点击次数:{count}</button>
<Child name={name} onClick={onClick} />
</div>
);
};
3.父组件向子组件传递了一个对象(React.useMemo())
useMemo()
返回的是一个 memoized 值。
如果useMemo
第二个参数依赖项没有发生改变,则直接返回缓存结果,不会重新渲染;如果没有提供依赖项数组,useMemo
在每次渲染时都会计算新的值。
javascript
import { useMemo, useState } from "react";
import { Child } from "./child";
export const Parent = () => {
const [count, setCount] = useState(0);
// const [userInfo, setUserInfo] = useState({ name: "小明", age: 18 });
const increment = () => setCount(count + 1);
const userInfo = useMemo(() => ({ name: "小明", age: 18 }), []);
return (
<div>
<button onClick={increment}>点击次数:{count}</button>
<Child userInfo={userInfo} />
</div>
);
};
归纳一波
三者都是用于解决子组件做多余渲染的性能问题
- React.memo() :用于处理组件父向子 未传递状态
用法: ------- memo()直接包裹子组件
- useCallback() :用于组件父向子传递了一个 函数
用法:------- useCallback()缓存函数
- useMemo() :用于组件父向子传递了一个 对象
用法:------- useMemo()缓存对象
useCallback
useMemo
都是为了解决父组件重新渲染时,未缓存的引用类型数据(函数,对象)将会重新指向新的地址,导致子组件理解props变化了,导致重新渲染(虽然代码未改变,但是此时已经是一个新的函数),使用他们来缓存对象,当第二个参数内的状态变化时才重新计算更新状态与函数。