首頁 > 軟體

React useCallback勾點的作用方法demo

2022-12-15 14:00:25

簡介

如果你還不熟悉勾點的概念,請務必檢視本文章,因為它對勾點的概念提供了一個非常好的、深入的概述,以及一些勾點的例子。

useCallback 勾點是用來快取一個記憶化的回撥函數,以節省任何重新計算的開銷。

這個勾點可以阻止一個元件重新渲染,除非它的道具發生了變化,這意味著我們現在可以隔離資源密集型的函數,這樣它們就不會在每個元件渲染時自動執行。

最好是展示一個有利於使用該勾點的場景,這樣我們就能更好地理解我們為達成一個問題所採取的步驟,然後再解釋使用useCallback 勾點背後的思考過程。

專案概述

我們將從搭建一個全新的React專案的腳手架開始。首先,我們將建立一個新的專案目錄,之後,我們將使用終端初始化一個新專案。

在這個過程中,你可以使用npmnpx或者yarn。你要執行的命令是:

  • npmnpm init react-app app-name
  • npx: npx create-react-app app-name
  • yarnyarn create react-app app-name

現在我們已經設定好了一切,讓我們直接進入有趣的部分。

專案進展

由於這是一個小專案,我們將把所有的程式碼放在根src 目錄下的App.js 檔案內,它看起來會是這樣的:

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列表,以及一個函數,一旦被呼叫,就會新增一個新的todo。這個元件的任務是將todos渲染到螢幕上,並在按下Add Todo 按鈕時新增一個新的todo。

然後,我們有其餘的App 元件,除了渲染和傳遞道具給MemoizedTodos 元件外,還在螢幕上顯示一個可以遞增的計數器。

而為了讓一切看起來更好一點,我們還將在我們的App.css 檔案中新增以下樣式:

.App {
  text-align: left;
  width: 80vw;
  margin: 5vh auto 0 auto;
}

那麼,問題出在哪裡?

現在,你可能會問自己:"這個應用程式有什麼問題?";的確,一切似乎都在正常工作。然而,問題是,每次我們點選+ 按鈕來增加計數器時,Todos 元件就會被重新渲染。

我們可以通過檢查控制檯來檢查,每次我們重新渲染Todos 元件時,都會列印到控制檯。

意外的Todos 元件的重新渲染

問題的根本原因

你看,在App 元件中,我們定義了addTodo 函數,它將在每次App 元件重新渲染時被重新建立。當App 元件的狀態發生變化時,它就會重新渲染,其中包括todos和計數器

我們正在使用[memo](https://reactjs.org/docs/react-api.html#reactmemo),所以Todos 元件不應該重新渲染,因為當計數增加時,todos 的狀態和addTodo 的功能都沒有改變。

因此,基本上,問題在於addTodo 是定義在App 元件內的,並且在該元件重新生成時被重新建立。

解決方法

實際上,我們有兩種方法可以解決這個問題:

  • 通過在App 元件之外定義addTodo 函數。
  • 通過對addTodo 函數的記憶化

雖然第一種方法似乎是明確的解決方案,但我們不能總是依靠將一個函數排除在元件的範圍之外,而使其成為一個純函數。

對函數進行記憶

然後我們再來看看useCallback 勾點,它正是通過對函數進行備忘來解決我們現在面臨的這個問題,以避免其重構。

我們所要做的就是從React中匯入useCallback 勾點,並將呼叫勾點的結果與勾點的回撥返回的狀態更新分配給addTodo 函數,就這樣:

const addTodo = useCallback(() => {
  setTodos((t) => [...t, "New Todo"]);
}, []);

而這個輕微的調整應該可以解決我們之前的問題。

現在,如果你想知道為什麼我們沒有把todos 陣列新增到勾點的依賴陣列中,那是因為React會拾取狀態,因為我們使用的是以回撥為引數的setTodos 函數,而不是一個陣列值。

如果我們要改變這一點,我們應該看到一個警告。

setState的值而不是回撥作為引數

useCallback依賴陣列的警告

總結

我希望你喜歡讀這篇文章,並希望你對useCallback 勾點是什麼,它的作用,以及什麼時候應該使用它有了更好的理解。

以上就是React useCallback勾點的作用方法demo的詳細內容,更多關於React useCallback勾點的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com