Bereaksi useCallbackKait


React useCallbackHook mengembalikan fungsi callback yang telah di memo.

Pikirkan memoisasi sebagai caching nilai sehingga tidak perlu dihitung ulang.

Hal ini memungkinkan kami untuk mengisolasi fungsi intensif sumber daya sehingga tidak akan berjalan secara otomatis pada setiap render.

Hook useCallbackhanya berjalan ketika salah satu dependensinya diperbarui.

Hal ini dapat meningkatkan kinerja.

The useCallbackdan useMemoHooks serupa. Perbedaan utama adalah useMemomengembalikan nilai memo dan useCallbackmengembalikan fungsi memo . Anda dapat mempelajari lebih lanjut tentang useMemo di bab useMemo .


Masalah

Salah satu alasan untuk menggunakan useCallbackadalah untuk mencegah komponen dari re-rendering kecuali props-nya telah berubah.

Dalam contoh ini, Anda mungkin berpikir bahwa Todoskomponen tidak akan dirender ulang kecuali todosperubahannya:

Ini adalah contoh yang mirip dengan yang ada di bagian React.memo .

Contoh:

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);

Coba jalankan ini dan klik tombol hitung kenaikan.

Anda akan melihat bahwa Todoskomponen merender ulang bahkan ketika todostidak berubah.

Mengapa ini tidak berhasil? Kami menggunakan memo, jadi Todoskomponen tidak boleh dirender ulang karena baik todosstatus maupun addTodofungsi tidak berubah saat hitungan bertambah.

Ini karena sesuatu yang disebut "kesetaraan referensial".

Setiap kali komponen dirender ulang, fungsinya akan dibuat ulang. Karena itu, addTodofungsinya sebenarnya telah berubah.


w3schools CERTIFIED . 2022

Dapatkan Sertifikasi!

Selesaikan modul React, kerjakan latihannya, ikuti ujiannya, dan dapatkan sertifikasi w3schools!!

$95 DAFTAR

Larutan

Untuk memperbaikinya, kita dapat menggunakan useCallbackpengait untuk mencegah fungsi dibuat ulang kecuali diperlukan.

Gunakan useCallbackHook untuk mencegah Todoskomponen dirender ulang secara tidak perlu:

Contoh:

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);

Sekarang Todoskomponen hanya akan dirender ulang ketika todosprop berubah.