Reagovat useCallbackHook


React useCallbackHook vrací funkci zpětného volání uloženou v paměti.

Pamatování si představte jako ukládání hodnoty do mezipaměti, aby ji nebylo nutné přepočítávat.

To nám umožňuje izolovat funkce náročné na zdroje, aby se automaticky nespouštěly při každém renderu.

Hook běží pouze tehdy, když se useCallbackaktualizuje jedna z jeho závislostí.

To může zlepšit výkon.

The useCallbacka useMemoHooks jsou podobné. Hlavní rozdíl je v tom, že useMemovrací zapamatovanou hodnotu a useCallbackvrací zapamatovanou funkci . Více o useMemo se můžete dozvědět v kapitole useMemo .


Problém

Jedním z důvodů použití useCallbackje zabránit komponentě v opětovném vykreslení, pokud se její podpěry nezměnily.

V tomto příkladu si můžete myslet, že Todoskomponenta se nebude znovu vykreslovat, pokud nedojde ke todoszměně:

Toto je podobný příklad jako v sekci React.memo .

Příklad:

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

Zkuste to spustit a klikněte na tlačítko zvýšení počtu.

Všimnete si, že se Todoskomponenta znovu vykresluje, i když se todosnezmění.

Proč to nefunguje? Používáme memo, takže Todoskomponenta by se neměla znovu vykreslovat, protože ani todosstav ani addTodofunkce se nemění, když se počet zvyšuje.

Je to kvůli něčemu, čemu se říká „referenční rovnost“.

Pokaždé, když se komponenta znovu vykreslí, její funkce se znovu vytvoří. Z tohoto důvodu se addTodofunkce skutečně změnila.


w3schools CERTIFIED . 2022

Získejte certifikaci!

Dokončete moduly React, proveďte cvičení, udělejte zkoušku a získejte certifikaci w3schools!!

95 $ PŘIHLÁSIT SE

Řešení

Abychom to napravili, můžeme pomocí useCallbackháku zabránit opětovnému vytvoření funkce, pokud to není nutné.

Použijte useCallbackHook, abyste zabránili Todoszbytečnému opětovnému vykreslování komponenty:

Příklad:

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

Nyní se Todoskomponenta znovu vykreslí pouze při změně todospodpěry.