Haken useCallbackreagieren


Der React useCallbackHook gibt eine gespeicherte Callback-Funktion zurück.

Stellen Sie sich Merken als Zwischenspeichern eines Werts vor, damit er nicht neu berechnet werden muss.

Dadurch können wir ressourcenintensive Funktionen isolieren, sodass sie nicht automatisch bei jedem Rendering ausgeführt werden.

Der useCallbackHook wird nur ausgeführt, wenn eine seiner Abhängigkeiten aktualisiert wird.

Dies kann die Leistung verbessern.

Die useCallbackund useMemoHaken sind ähnlich. Der Hauptunterschied besteht darin, dass useMemoein gespeicherter Wert und useCallbackeine gespeicherte Funktion zurückgegeben werden . Mehr über useMemo erfahren Sie im Kapitel useMemo .


Problem

Ein Grund für die Verwendung useCallbackbesteht darin, zu verhindern, dass eine Komponente erneut gerendert wird, es sei denn, ihre Requisiten haben sich geändert.

In diesem Beispiel könnten Sie denken, dass die TodosKomponente nicht erneut gerendert wird, es sei denn, die todosÄnderung:

Dies ist ein ähnliches Beispiel wie im Abschnitt React.memo .

Beispiel:

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

Versuchen Sie, dies auszuführen, und klicken Sie auf die Schaltfläche zum Erhöhen der Anzahl.

Sie werden feststellen, dass die TodosKomponente auch dann neu gerendert wird, wenn todossich nichts ändert.

Warum funktioniert das nicht? Wir verwenden memo, daher sollte die TodosKomponente nicht erneut gerendert werden, da sich weder der todosZustand noch die addTodoFunktion ändern, wenn der Zähler erhöht wird.

Dies liegt an etwas, das als "referenzielle Gleichheit" bezeichnet wird.

Jedes Mal, wenn eine Komponente neu gerendert wird, werden ihre Funktionen neu erstellt. Aus diesem Grund hat sich die addTodoFunktion tatsächlich geändert.


w3schools CERTIFIED . 2022

Zertifiziert werden!

Absolvieren Sie die React-Module, machen Sie die Übungen, machen Sie die Prüfung und werden Sie w3schools-zertifiziert!!

$ 95 REGISTRIEREN

Lösung

Um dies zu beheben, können wir den useCallbackHook verwenden, um zu verhindern, dass die Funktion neu erstellt wird, es sei denn, dies ist erforderlich.

Verwenden Sie den useCallbackHaken, um zu verhindern, dass die TodosKomponente unnötig neu gerendert wird:

Beispiel:

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

Jetzt Todoswird die Komponente nur dann neu gerendert, wenn sich die todosRequisite ändert.