React useCallbackHook


React useCallbackHook trả về một hàm gọi lại đã ghi nhớ.

Hãy coi ghi nhớ như một giá trị lưu vào bộ nhớ đệm để nó không cần phải tính toán lại.

Điều này cho phép chúng tôi cô lập các chức năng sử dụng nhiều tài nguyên để chúng không tự động chạy trên mỗi lần hiển thị.

useCallbackHook chỉ chạy khi một trong các phần phụ thuộc của nó cập nhật .

Điều này có thể cải thiện hiệu suất.

The useCallbackuseMemoHooks cũng tương tự như vậy. Sự khác biệt chính là useMemotrả về một giá trị được ghi nhớ và useCallbacktrả về một hàm được ghi nhớ . Bạn có thể tìm hiểu thêm về useMemo trong chương useMemo .


Vấn đề

Một lý do để sử dụng useCallbacklà ngăn một thành phần hiển thị lại trừ khi các đạo cụ của nó đã thay đổi.

Trong ví dụ này, bạn có thể nghĩ rằng Todosthành phần sẽ không hiển thị lại trừ khi todosthay đổi:

Đây là một ví dụ tương tự với ví dụ trong phần React.memo .

Thí dụ:

index.js

import { useState } from "react";
import ReactDOM from "react-dom";
import Todos from "./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 (
    <>
      <Todos todos={todos} addTodo={addTodo} />
      <hr />
      <div>
        Count: {count}
        <button onClick={increment}>+</button>
      </div>
    </>
  );
};

ReactDOM.render(<App />, document.getElementById('root'));

Todos.js

import { memo } from "react";

const Todos = ({ todos, addTodo }) => {
  console.log("child render");
  return (
    <>
      <h2>My Todos</h2>
      {todos.map((todo, index) => {
        return <p key={index}>{todo}</p>;
      })}
      <button onClick={addTodo}>Add Todo</button>
    </>
  );
};

export default memo(Todos);

Hãy thử chạy cái này và nhấp vào nút tăng số lượng.

Bạn sẽ nhận thấy rằng Todosthành phần hiển thị lại ngay cả khi todoskhông thay đổi.

Tại sao cai nay không hoạt động? Chúng tôi đang sử dụng memo, vì vậy Todosthành phần không nên hiển thị lại vì cả todostrạng thái và addTodohàm đều không thay đổi khi số lượng được tăng lên.

Điều này là do một thứ gọi là "bình đẳng tham chiếu".

Mỗi khi một thành phần hiển thị, các chức năng của nó sẽ được tạo lại. Bởi vì điều này, addTodochức năng đã thực sự thay đổi.


w3schools CERTIFIED . 2022

Được chứng nhận!

Hoàn thành các mô-đun React, làm bài tập, làm bài kiểm tra và được chứng nhận w3schools !!

$ 95 GHI DANH

Giải pháp

Để khắc phục điều này, chúng ta có thể sử dụng useCallbackhook để ngăn hàm được tạo lại trừ khi cần thiết.

Sử dụng useCallbackHook để ngăn Todosthành phần hiển thị không cần thiết:

Thí dụ:

index.js

import { useState, useCallback } from "react";
import ReactDOM from "react-dom";
import Todos from "./Todos";

const App = () => {
  const [count, setCount] = useState(0);
  const [todos, setTodos] = useState([]);

  const increment = () => {
    setCount((c) => c + 1);
  };
  const addTodo = useCallback(() => {
    setTodos((t) => [...t, "New Todo"]);
  }, [todos]);

  return (
    <>
      <Todos todos={todos} addTodo={addTodo} />
      <hr />
      <div>
        Count: {count}
        <button onClick={increment}>+</button>
      </div>
    </>
  );
};

ReactDOM.render(<App />, document.getElementById('root'));

Todos.js

import { memo } from "react";

const Todos = ({ todos, addTodo }) => {
  console.log("child render");
  return (
    <>
      <h2>My Todos</h2>
      {todos.map((todo, index) => {
        return <p key={index}>{todo}</p>;
      })}
      <button onClick={addTodo}>Add Todo</button>
    </>
  );
};

export default memo(Todos);

Bây giờ Todosthành phần sẽ chỉ hiển thị lại khi todosprop thay đổi.