網站首頁 編程語言 正文
React.memo怎么用
React.memo()
是一個高階組件 (HOC),它接收一個組件A作為參數并返回一個組件B,如果組件B的 props(或其中的值)沒有改變,則組件 B 會阻止組件 A 重新渲染 。
下面我們看一個示例:
const ParentComponent = () => { const [ count, setCount ] = useState(0); const handleParent = () => { console.log('clicked ParentComponent'); setCount(preCount => preCount + 1); }; return ( <div> <div onClick={handleParent}>父組件,點擊了{count}次</div> <ChildrenComponent /> </div> ); }; const ChildrenComponent = () => { console.log('ChildrenComponent rending'); return <div>我是子組件</div>; };
點擊父組件:
可以看到控制臺中輸出了子組件里的打印,表示子組件 rerender 了,如果子組件中有龐大的 dom 結構和計算,那是非常消耗性能的事,通過 memo 我們可以對比 render 前后的 prop 變化,如果沒有變化就不會重新 render 子組件:
const ChildrenComponent = memo(() => { console.log('ChildrenComponent rending'); return <div>我是子組件</div>; });
把子組件通過 memo 包裹后就不會因為父組件更新導致的 render 了
React.useMemo怎么用
React.memo()
是一個 HOC,而 useMemo() 是一個 React Hook。 使用 useMemo()
,我們可以返回記憶值來避免函數的依賴項沒有改變的情況下重新渲染。并且可以避免在每次渲染時都進行高開銷的計算的優化的策略。
const sum = ()=>{ return a+b } const result = useMemo(()=>{sum()},[a,b]) // 只有在a或者b的值變化時才會觸發sum函數執行
React.memo()和useMemo()的主要區別
從上面的例子中,我們可以看到 React.memo()
和 useMemo()
之間的主要區別:
-
React.memo()
是一個高階組件,我們可以使用它來包裝我們不想重新渲染的組件,除非其中的 props 發生變化 -
useMemo()
是一個 React Hook,我們可以使用它在組件中包裝函數。 我們可以使用它來確保該函數中的值僅在其依賴項之一發生變化時才重新計算
雖然 memoization 似乎是一個可以隨處使用的巧妙小技巧,但只有在絕對需要這些性能提升時才應該使用它。 Memoization 會占用運行它的機器上的內存空間,因此可能會導致意想不到的效果。
React.useCallback怎么用
我們看一下下面這個示例:
const ParentComponent = () => { const [ count, setCount ] = useState(0); const [ childCount, setChildCount ] = useState(0) const handleChildren = () => { console.log('clicked ChildrenComponent'); setChildCount(preCount => preCount + 1) }; const handleParent = () => { console.log('clicked ParentComponent'); setCount(preCount => preCount + 1); }; return ( <div> <div onClick={handleParent}>父組件,點擊了{count}次</div> <ChildrenComponent handleChildren={handleChildren} data={childCount}/> </div> ); }; const ChildrenComponent = memo(({ handleChildren, data }) => { console.log('ChildrenComponent rending', data); return <div onClick={handleChildren}>ChildrenComponent,子組件被點擊了{data}次 </div>; });
在上面的例子中,我們把子組件通過 React.memo 包起來了,希望在父組件更新的時候,子組件不會 再次render,那么會和我們想的一樣嗎?
當點擊父組件時,子組件再次 render 了, 因為子組件的 prop 傳入了有函數 handleChildren ,當點擊父組件時更改了 state 值導致父組件重新 render,那么原來的 hanldeChildren 函數和更新后的 hanldeChildren 顯然處在不同的執行環境中,他們并不是一個函數,在內存中不是同一個引用地址,所以就導致了 memo 的包裹無效,因為 prop 改變了。
useCallback 需要傳入兩個參數
- callback(僅僅是個函數),把要做事情的函數放在callback函數體內執行
- deps 要做事情的函數需要引入的外部參數或者是依賴參數
const handleChildrenCallback = useCallback(() => { handleChildren(); }, []);// 咱們不需要就不要傳入
useCallback 返回一個 memoized 回調函數。在依賴參數不變的情況下,返回的回調函數是同一個引用地址
注意 每當依賴參數發生改變useCallback就會自動重新返回一個新的 memoized 函數(地址發生改變)
上面就是沒有使用 useCallBack 的使用場景,現在我們知道了,把要傳遞的函數參數通過 useCallBack 包裹一層,這樣返回的回調函數就是同一個引用地址,這樣子組件就不會 rerender 了:
const handleChildren = useCallback(() => { console.log('clicked ChildrenComponent'); setChildCount(preCount => preCount + 1) }, [setChildCount]);
現在在點擊父組件后,子組件就不會再 rerender 了。
大伙現在應該明白了useCallback的作用了,它主要用來配合memo用于優化子組件的渲染次數
memo與useMemo及useCallback的區別
- memo用來優化函數組件的重復渲染行為,針對的是一個組件
- useMemo返回一個memoized的值
- 本質都是用同樣的算法來判定依賴是否發生改變,繼而決定是否觸發memo或者useMemo中的邏輯,利用memo就可以避免不必要的重復計算,減少資源浪費
- useCallback返回一個memoized的函數
防止不必要的 effect
如果一個值被 useEffect 依賴,那它可能需要被緩存,這樣可以避免重復執行 effect。
const Component = () => { // 在 re-renders 之間緩存 a 的引用 const a = useMemo(() => ({ test: 1 }), []); useEffect(() => { // 只有當 a 的值變化時,這里才會被觸發 doSomething(); }, [a]); // the rest of the code };
useCallback 同理:
const Component = () => { // 在 re-renders 之間緩存 fetch 函數 const fetch = useCallback(() => { console.log('fetch some data here'); }, []); useEffect(() => { // 僅fetch函數的值被改變時,這里才會被觸發 fetch(); }, [fetch]); // the rest of the code };
當變量直接或者通過依賴鏈成為 useEffect 的依賴項時,那它可能需要被緩存。這也是 useMemo 和 useCallback 得基本用法之一。
原文鏈接:https://blog.csdn.net/qq_49900295/article/details/127383204
相關推薦
- 2022-07-07 redis遠程連接不上的解決辦法_Redis
- 2022-11-14 開發板NFS掛載方案
- 2022-10-12 sql中exists的基本用法示例_MsSql
- 2022-02-26 Assert.assertEquals()方法參數詳解_Android
- 2022-08-17 python熱力圖實現的完整實例_python
- 2022-04-01 k8s使用docker作為運行時卡死解決辦法
- 2022-05-12 van-checkbox 全選,解決單個點擊后會取消全部的問題
- 2022-09-09 Python?OpenCV?Canny邊緣檢測算法的原理實現詳解_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支