React useCallback鉤子的作用方法demo
簡介
如果你還不熟悉鉤子的概念,請務必查看本文章,因為它對鉤子的概念提供了一個非常好的、深入的概述,以及一些鉤子的例子。
useCallback 鉤子是用來緩存一個記憶化的回調(diào)函數(shù),以節(jié)省任何重新計算的開銷。
這個鉤子可以阻止一個組件重新渲染,除非它的道具發(fā)生了變化,這意味著我們現(xiàn)在可以隔離資源密集型的函數(shù),這樣它們就不會在每個組件渲染時自動運行。
最好是展示一個有利于使用該鉤子的場景,這樣我們就能更好地理解我們?yōu)檫_成一個問題所采取的步驟,然后再解釋使用useCallback 鉤子背后的思考過程。
項目概述
我們將從搭建一個全新的React項目的腳手架開始。首先,我們將創(chuàng)建一個新的項目目錄,之后,我們將使用終端初始化一個新項目。
在這個過程中,你可以使用npm、npx或者yarn。你要運行的命令是:
- npm。
npm init react-app app-name - npx
: npx create-react-app app-name - yarn。
yarn create react-app app-name
現(xiàn)在我們已經(jīng)設置好了一切,讓我們直接進入有趣的部分。
項目進展
由于這是一個小項目,我們將把所有的代碼放在根src 目錄下的App.js 文件內(nèi),它看起來會是這樣的:
import { useState, memo } from "react";
import './App.css';
const Todos = ({ todos, addTodo }) => {
console.log("child render");
return (
<div className="todos-container">
<h2>My Todos</h2>
<div className="todos">
{todos.map((todo, index) => {
return <p key={index}>{todo}</p>;
})}
</div>
<button onClick={addTodo}>Add Todo</button>
</div>
);
};
const MemoizedTodos = memo(Todos);
const App = () => {
const [count, setCount] = useState(0);
const [todos, setTodos] = useState([]);
const increment = () => {
setCount((c) => c + 1);
};
const addTodo = () => {
setTodos((t) => [...t, "New Todo"]);
};
return (
<div className="App">
<MemoizedTodos
todos={todos}
addTodo={addTodo}
/>
<hr />
<div className="counter-container">
<p>Count: {count}</p>
<button onClick={increment}>+</button>
</div>
</div>
);
};
export default App;
這里有相當多的東西需要解壓,所以讓我們看看我們有什么。
首先,我們定義了一個Todos 組件,它的道具是一個todos列表,以及一個函數(shù),一旦被調(diào)用,就會添加一個新的todo。這個組件的任務是將todos渲染到屏幕上,并在按下Add Todo 按鈕時添加一個新的todo。
然后,我們有其余的App 組件,除了渲染和傳遞道具給MemoizedTodos 組件外,還在屏幕上顯示一個可以遞增的計數(shù)器。
而為了讓一切看起來更好一點,我們還將在我們的App.css 文件中添加以下樣式:
.App {
text-align: left;
width: 80vw;
margin: 5vh auto 0 auto;
}
那么,問題出在哪里?
現(xiàn)在,你可能會問自己:"這個應用程序有什么問題?";的確,一切似乎都在正常工作。然而,問題是,每次我們點擊+ 按鈕來增加計數(shù)器時,Todos 組件就會被重新渲染。
我們可以通過檢查控制臺來檢查,每次我們重新渲染Todos 組件時,都會打印到控制臺。

意外的Todos 組件的重新渲染
問題的根本原因
你看,在App 組件中,我們定義了addTodo 函數(shù),它將在每次App 組件重新渲染時被重新創(chuàng)建。當App 組件的狀態(tài)發(fā)生變化時,它就會重新渲染,其中包括todos和計數(shù)器。
我們正在使用[memo](https://reactjs.org/docs/react-api.html#reactmemo),所以Todos 組件不應該重新渲染,因為當計數(shù)增加時,todos 的狀態(tài)和addTodo 的功能都沒有改變。
因此,基本上,問題在于addTodo 是定義在App 組件內(nèi)的,并且在該組件重新生成時被重新創(chuàng)建。
解決方法
實際上,我們有兩種方法可以解決這個問題:
- 通過在
App組件之外定義addTodo函數(shù)。 - 通過對
addTodo函數(shù)的記憶化
雖然第一種方法似乎是明確的解決方案,但我們不能總是依靠將一個函數(shù)排除在組件的范圍之外,而使其成為一個純函數(shù)。
對函數(shù)進行記憶
然后我們再來看看useCallback 鉤子,它正是通過對函數(shù)進行備忘來解決我們現(xiàn)在面臨的這個問題,以避免其重構(gòu)。
我們所要做的就是從React中導入useCallback 鉤子,并將調(diào)用鉤子的結(jié)果與鉤子的回調(diào)返回的狀態(tài)更新分配給addTodo 函數(shù),就這樣:
const addTodo = useCallback(() => {
setTodos((t) => [...t, "New Todo"]);
}, []);
而這個輕微的調(diào)整應該可以解決我們之前的問題。
現(xiàn)在,如果你想知道為什么我們沒有把todos 數(shù)組添加到鉤子的依賴數(shù)組中,那是因為React會拾取狀態(tài),因為我們使用的是以回調(diào)為參數(shù)的setTodos 函數(shù),而不是一個數(shù)組值。
如果我們要改變這一點,我們應該看到一個警告。

setState的值而不是回調(diào)作為參數(shù)

useCallback依賴數(shù)組的警告
總結(jié)
我希望你喜歡讀這篇文章,并希望你對useCallback 鉤子是什么,它的作用,以及什么時候應該使用它有了更好的理解。
以上就是React useCallback鉤子的作用方法demo的詳細內(nèi)容,更多關于React useCallback鉤子的資料請關注腳本之家其它相關文章!
相關文章
react中使用js實現(xiàn)頁面滾動監(jiān)聽(推薦)
這篇文章主要介紹了react中使用js實現(xiàn)頁面滾動監(jiān)聽,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2024-04-04
React實現(xiàn)數(shù)字滾動組件numbers-scroll的示例詳解
數(shù)字滾動組件,也可以叫數(shù)字輪播組件,這個名字一聽就是非常普通常見的組件。本文將利用React實現(xiàn)這一組件,感興趣的小伙伴可以了解一下2023-03-03
React-Native使用Mobx實現(xiàn)購物車功能
本篇文章主要介紹了React-Native使用Mobx實現(xiàn)購物車功能,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-09-09

