رد فعل useCallback
هوك
يقوم useCallback
React 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
تغيرت الوظيفة بالفعل.
الحصول على شهادة!
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
تتغير الخاصية.