網站首頁 編程語言 正文
正確使用useCallback useMemo的姿勢
說起useCallback useMemo大家肯定在React都不陌生,但是真正了解它們的作用,還是有一部分同學對此是一知半解,只是知道用它,卻不知道它真正的含義。
今天帶大家學習一下它們的真正蘊藏的作用。
useCallback useMemo 都是記憶函數,什么是記憶函數呢?
用個最簡單的例子來講 useState 也是記憶函數 細想一下以下代碼,為什么setcount每次改變會引起組件重新render,但是count為什么不會再次被初始值0進行賦值呢?
如果是這樣的話,我們就不能修改成功了,所以說存在某個地方保存了state的值,而這個地方是不會受到render的影響的,state就被緩存起來了。
const [count, setcount] = useState(0);
那么 useCallback useMemo 也是被緩存起來了嗎?讓我們逐個來看看
useCallback
useCallback 的作用是啥?我們來看看下面的代碼:
import React, { memo, useCallback, useState } from "react";
const HookTest = memo(() => {
const [count, setcount] = useState(0);
const [num, setnum] = useState(100);
const showCount = () => {
console.log("沒事執行玩玩", count + "$");
};
return (
<div>
<h2>HookTest:useCallback----useMemo</h2>
<h3>useCallBack</h3>
<h4>
count:{count}---num:{num}
</h4>
<button onClick={showCount}>showCount</button>
<button onClick={(e) => setcount(count + 3)}>+3</button>
<button onClick={(e) => setnum(num * 10)}>*10</button>
);
});
export default HookTest;
正常執行的話,修改count 和 num 都會觸發 render ,這是毫無疑問的。那么showCount 每次render也會被重新創建一次,這也是情理之中的。 但是我們想想,真的有必要每次render都重新創建showCount 嗎?現在可能只有一個函數,函數體也簡單,重新創建也影響不了什么,但是真正開發的時候卻是我們要考慮的問題。 所以 useCallback 來幫我們解決這個問題了!
const showCount = () => {
console.log("沒事執行玩玩", count + "$");
};
const showCount = useCallback(() => {
console.log("沒事執行玩玩", count + "$");
}, [count]);
useCallback 接收兩個參數 第一個為需要緩存的函數 第二個為數組,裝載依賴
那么現在的 showCount 和之前的又有什么不一樣呢?
現在的 showCount 是被緩存起來了,組件render時,如果裝載依賴的數組中的依賴未更新,那么依然采用緩存的函數。也就是說只有當我點修改count時觸發更新組件render后,showCount 也重新創建,但是當我進行其他的操作引起組件render時,由于此時條件依賴跟裝載依賴的數組中依賴毫無關系,showCount 用的是緩存里的函數。這就是 useCallback 的正確使用方法啦~
useMemo
看下面案例:
import React, { memo, useMemo, useState } from "react";
const HookTest = memo(() => {
const [count, setcount] = useState(0);
const [arr, setarr] = useState([
{
flag: true,
num: 20,
},
{
flag: false,
num: 10,
},
{
flag: true,
num: 40,
},
{
flag: true,
num: 60,
},
{
flag: true,
num: 70,
},
{
flag: true,
num: 80,
},
]);
const allNum = () =>
arr.reduce(
(preValue, currentValue) =>
currentValue.flag ? preValue + currentValue.num : preValue,
0
);
return (
<div>
<h2>HookTest:useCallback----useMemo</h2>
<h3>useMemo</h3>
<h4>
count:{count}
</h4>
<button onClick={(e) => setcount(count + 3)}>+3</button>
<h4>all:{allNum}</h4>
</div>
);
});
export default HookTest;
很簡單的小案例,根據條件對數組求和操作,同樣我們點擊修改count 然后組件重新render
此時我們考慮一個問題,是不是 allNum 又進行了一次復雜的運行然后得到結果?現在看來才幾條數據,怎么復雜了,我們得考慮數組若是幾百上千上萬呢?我們都知道組件渲染是很頻繁的,那么每次渲染我們真的有必要去每次進行復雜的運算嗎?
所以這就是性能優化的另一個點了 引出 useMemo來幫助我們解決
將allNum 改造后:
const allNum = () =>
arr.reduce(
(preValue, currentValue) =>
currentValue.flag ? preValue + currentValue.num : preValue,
0
);
const allNum = useMemo(
() =>
arr.reduce(
(preValue, currentValue) =>
currentValue.flag ? preValue + currentValue.num : preValue,
0
),
[arr]
);
useMemo 同樣接收兩個參數 第一個參數是函數的返回值!! 第二個為數組,裝載依賴
用了之后呢?有那些改變呢?
現在 allNum 不再是一個函數了,而是一個返回值現在如果進行和依賴數組無關的render時,allNum 將采用上次緩存的返回值,不用再去傻傻的計算一遍啦。
總結
簡單給大家總結下:
- useCallback 緩存函數
- useMemo 緩存函數返回值
- 都是解決組件頻繁渲染從而頻繁創建函數及頻繁運行函數
- 正確的思路應該是 跟我有關的時候我才需要去重新創建函
原文鏈接:https://juejin.cn/post/7128664391393738789
相關推薦
- 2022-09-30 C#?wpf?Grid中實現控件拖動調整大小的示例代碼_C#教程
- 2022-10-24 六個Python3中使用最廣泛的內置函數總結_python
- 2022-04-30 DataGridView控件常用屬性介紹_C#教程
- 2023-01-17 Golang排序和查找使用方法介紹_Golang
- 2022-07-11 SpringBoot事件機制@EventListener的簡單使用
- 2022-12-29 R語言apply系列函數實例詳解_R語言
- 2022-08-20 Django細致講解多對多使用through自定義中間表方法_python
- 2023-02-17 Golang實踐指南之獲取目錄文件列表_Golang
- 最近更新
-
- 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同步修改后的遠程分支