React中memo useCallback useMemo方法作用及使用場(chǎng)景
memo()、useCallback()、useMemo()使用場(chǎng)景
當(dāng)父組件的props或state變化時(shí),render重新渲染,但傳遞給子組件的props沒有發(fā)生變化說著只是簡(jiǎn)單調(diào)用了一下子組件,這時(shí)子組件也要重新渲染,這就導(dǎo)致了組件的不必要的渲染
React.memo()
當(dāng)父組件只是簡(jiǎn)單調(diào)用子組件,并未給子組件傳遞任何屬性,我們可以通過memo來控制函數(shù)組件的渲染
React.memo()將組件作為函數(shù)(memo)的參數(shù),函數(shù)的返回值(Child)是一個(gè)新的組件。
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}>點(diǎn)擊次數(shù):{count}</button>
<Child />
</div>
);
};
import {memo} from 'react'
export const Child=memo(()=>{
consloe.log('渲染了')
return <div>子組件</div>
})
//使用memo()包裹后的組件,在Parent組件重新渲染更新時(shí),Child組件并沒有重新渲染更新
當(dāng)我們傳值給子組件時(shí),這時(shí)使用memo函數(shù)就對(duì)控制組件的更新不起作用了
父組件
import { useState } from "react";
import { Child } from "./child";
export const Parent = () => {
const [count, setCount] = useState(0);
const [name, setName] = useState("小明");
const increment = () => setCount(count + 1);
const onClick = (name: string) => {
setName(name);
};
return (
<div>
<button onClick={increment}>點(diǎn)擊次數(shù):{count}</button>
<Child name={name} onClick={onClick} />
</div>
);
};
子組件
import { memo } from "react";
export const Child = memo(
(props: { name: string; onClick: (value: any) => void }) => {
const { name, onClick } = props;
console.log("渲染了", name, onClick);
return (
<>
<div>子組件</div>
<button onClick={() => onClick("小紅")}>改變 name 值</button>
</>
);
}
);
出現(xiàn)這樣結(jié)果的原因:
點(diǎn)擊父組件按鈕時(shí),改變了父組件的count,導(dǎo)致父組件重新渲染
父組件重新渲染時(shí),重新創(chuàng)建了onClick函數(shù),導(dǎo)致傳遞給子組件的onClick屬性發(fā)生了變化,導(dǎo)致子組件重新渲染
如果傳遞給子組件的只有基本數(shù)據(jù)類型將不會(huì)重新渲染
注意: 如果直接使用useState解構(gòu)的setName傳給子組件, 子組件將不會(huì)重復(fù)渲染,因?yàn)榻鈽?gòu)出來的是一個(gè)memoized 函數(shù)。
React.useCallback()
所以,在這種情況下我們使用React.useCallback() useCallback(fn, deps)
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鉤子包裹的回調(diào)函數(shù)是memoized函數(shù),他初次調(diào)用該函數(shù)時(shí),緩存參數(shù)和計(jì)算結(jié)果,再次調(diào)用這個(gè)函數(shù)時(shí),如果第二個(gè)參數(shù)依賴項(xiàng)沒有發(fā)生改變,則直接返回緩存結(jié)果,不會(huì)重新渲染
const onClick = useCallback((name: string) => {
setName(name);
}, []);
return (
<div>
<button onClick={increment}>點(diǎn)擊次數(shù):{count}</button>
<Child name={name} onClick={onClick} />
</div>
);
};
但當(dāng)我們傳遞的屬性name不字符串,而是對(duì)象時(shí)
父組件
import { useCallback, 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 = { name: "小明", age: 18 };
return (
<div>
<button onClick={increment}>點(diǎn)擊次數(shù):{count}</button>
<Child userInfo={userInfo} />
</div>
);
};
子組件
import { memo } from "react";
export const Child = memo(
(props: { userInfo: { name: string; age: number } }) => {
const { userInfo } = props;
console.log("渲染了", userInfo);
return (
<>
<div>名字: {userInfo.name}</div>
<div>年齡:{userInfo.age}</div>
</>
);
}
);
點(diǎn)擊父組件count,看到子組件每次都重新渲染了。 分析原因跟調(diào)用函數(shù)是一樣的:
- 點(diǎn)擊父組件按鈕,觸發(fā)父組件重新渲染;
- 父組件渲染,
const userInfo = { name: "小明", age: 18 };一行會(huì)重新生成一個(gè)新對(duì)象,導(dǎo)致傳遞給子組件的 userInfo 屬性值變化,進(jìn)而導(dǎo)致子組件重新渲染。 - 注意: 如果使用
useState解構(gòu)的userInfo, 子組件將不會(huì)重復(fù)渲染,因?yàn)榻鈽?gòu)出來的是一個(gè)memoized 值。
這時(shí)我們使用 React.useMemo() useMemo(() => fn, dep)
React.useMemo()
useMemo()返回的是一個(gè) memoized 值。
如果沒有提供依賴項(xiàng)數(shù)組,useMemo 在每次渲染時(shí)都會(huì)計(jì)算新的值。
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}>點(diǎn)擊次數(shù):{count}</button>
<Child userInfo={userInfo} />
</div>
);
};
對(duì)比useCallback() 和useMemo()
useCallback(fn, deps) 返回該回調(diào)函數(shù)的memoized回調(diào)函數(shù)
const onClick = useCallback((name: string) => {
setName(name);
}, []);
useMemo(() => fn, dep) 返回的是一個(gè) memoized 值。
const userInfo = useMemo(() => ({ name: "小明", age: 18 }), []);以上就是React中memo useCallback useMemo方法作用及使用場(chǎng)景的詳細(xì)內(nèi)容,更多關(guān)于React useCallback useMemo的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- 關(guān)于react中useCallback的用法
- react中關(guān)于useCallback的用法
- 詳解react中useCallback內(nèi)部是如何實(shí)現(xiàn)的
- React Hooks之使用useCallback和useMemo進(jìn)行性能優(yōu)化方式
- React?useCallback使用方法詳解
- 解析React中useMemo與useCallback的區(qū)別
- react組件memo useMemo useCallback使用區(qū)別示例
- React?中?memo?useMemo?useCallback?到底該怎么用
- React中useCallback 的基本使用和原理小結(jié)
相關(guān)文章
React Native模塊之Permissions權(quán)限申請(qǐng)的實(shí)例相機(jī)
這篇文章主要介紹了React Native模塊之Permissions權(quán)限申請(qǐng)的實(shí)例相機(jī)的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下2017-09-09
react native基于FlatList下拉刷新上拉加載實(shí)現(xiàn)代碼示例
這篇文章主要介紹了react native基于FlatList下拉刷新上拉加載實(shí)現(xiàn)代碼示例2018-09-09
react-pdf實(shí)現(xiàn)將pdf文件轉(zhuǎn)為圖片,用于頁面展示
這篇文章主要介紹了react-pdf實(shí)現(xiàn)將pdf文件轉(zhuǎn)為圖片,用于頁面展示問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07
使用Ant Design Anchor組件的一個(gè)坑及解決
這篇文章主要介紹了使用Ant Design Anchor組件的一個(gè)坑及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04
比ant更豐富Modal組件功能實(shí)現(xiàn)示例詳解
這篇文章主要為大家介紹了比ant更豐富Modal組件功能實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
React Native 資源包拆分實(shí)戰(zhàn)分析
這篇文章主要為大家介紹了React Native 資源包拆分實(shí)戰(zhàn)分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08

