ตอบสนองuseCallback
ตะขอ
React useCallback
Hook ส่งคืนฟังก์ชันการโทรกลับที่บันทึกไว้
ให้คิดว่าการจดบันทึกเป็นการแคชค่าเพื่อจะได้ไม่ต้องคำนวณใหม่
ซึ่งช่วยให้เราสามารถแยกฟังก์ชันที่เน้นทรัพยากรเพื่อไม่ให้ทำงานโดยอัตโนมัติในทุกการเรนเดอร์
Hook ทำงานเฉพาะเมื่อมี การuseCallback
อัปเดตการพึ่งพาอย่างใดอย่างหนึ่งเท่านั้น
นี้สามารถปรับปรุงประสิทธิภาพการทำงาน
The useCallback
และuseMemo
Hooks มีความคล้ายคลึงกัน ความแตกต่างหลัก ๆ คือ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
ฟังก์ชันจึงเปลี่ยนไปจริงๆ
สารละลาย
ในการแก้ไขปัญหานี้ เราสามารถใช้useCallback
hook เพื่อป้องกันไม่ให้มีการสร้างฟังก์ชันขึ้นใหม่เว้นแต่จำเป็น
ใช้useCallback
Hook เพื่อป้องกันไม่ให้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
เสามีการเปลี่ยนแปลง