رد فعل useCallbackهوك


يقوم useCallbackReact Hook بإرجاع وظيفة رد الاتصال memoized.

فكر في الحفظ كذاكرة تخزين مؤقت لقيمة بحيث لا تحتاج إلى إعادة حسابها.

هذا يسمح لنا بعزل وظائف الموارد كثيفة بحيث لا يتم تشغيلها تلقائيًا في كل تصيير.

يعمل useCallbackالخطاف فقط عند تحديث أحد تبعياته.

هذا يمكن أن يحسن الأداء.

الخطاف و الخطاف متشابهان useCallback. useMemoيتمثل الاختلاف الرئيسي useMemoفي إرجاع قيمة ذاكرة وإرجاع دالةuseCallback محفوظة . يمكنك معرفة المزيد حول useMemo في فصل useMemo .


مشكلة

أحد أسباب الاستخدام useCallbackهو منع المكون من إعادة العرض ما لم تتغير الدعائم الخاصة به.

في هذا المثال ، قد تعتقد أن Todosالمكون لن يعاد تصيير ما لم يتم todosالتغيير:

هذا مثال مشابه للمثال الموجود في قسم React.memo .

مثال:

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

حاول تشغيل هذا وانقر فوق زر زيادة العد.

ستلاحظ أن Todosالمكون يعيد تصيير حتى عندما todosلا يتغير.

لماذا هذا لا يعمل؟ نحن نستخدم memo، لذلك Todosلا يجب إعادة تصيير المكون نظرًا لأنه لا todosالحالة ولا addTodoالوظيفة تتغير عند زيادة العدد.

هذا بسبب ما يسمى "المساواة المرجعية".

في كل مرة يُعاد تصيير أحد المكونات ، يتم إعادة إنشاء وظائفه. لهذا السبب ، addTodoتغيرت الوظيفة بالفعل.


w3schools CERTIFIED . 2022

الحصول على شهادة!

أكمل وحدات React ، ونفّذ التمارين ، وخذ الامتحان واحصل على شهادة w3schools !!

95 دولارًا ENROLL

المحلول

لإصلاح ذلك ، يمكننا استخدام useCallbackالخطاف لمنع إعادة إنشاء الوظيفة ما لم يكن ذلك ضروريًا.

استخدم useCallbackالخطاف لمنع Todosالمكون من إعادة العرض دون داع:

مثال:

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

الآن Todosسيتم إعادة تصيير المكون فقط عندما todosتتغير الخاصية.