Phản ứng kết xuất phần tử không cần thiết
Tôi vừa mới bắt đầu học React và đang tập hợp một ứng dụng nhỏ thực hiện các lệnh gọi đến một API báo giá. API có một điểm cuối trả về một trích dẫn ngẫu nhiên. Khi ứng dụng tải lần đầu, nó thực hiện cuộc gọi tới API và hiển thị báo giá và có một nút có thể được nhấp vào để nhận báo giá ngẫu nhiên mới (lệnh gọi mới tới API).
Tôi có một thành phần gốc có tên là Ứng dụng. Thành phần này có một thành phần QuoteWrap khi còn nhỏ. Thành phần QuoteWrap có hai nút con: nút được sử dụng để nhận một trích dẫn ngẫu nhiên mới và một thành phần Trích dẫn hiển thị tác giả của câu trích dẫn và chính câu trích dẫn đó. Đây là mã bên trong thành phần QuoteWrap:
export default function QuoteWrap() {
const { quoteData, isLoading, fireNewCall } = useQuote();
const handleClick = () => {
fireNewCall();
};
return(
<>
<button onClick={handleClick}>Get random quote</button>
{ isLoading ?
<h2>Loading...</h2>
:
<Quote author={quoteData.author} quote={quoteData.quote} />
}
</>
);
}
useQuote () là một hook tùy chỉnh quản lý các lệnh gọi đến API và trả về 3 giá trị: 1- dữ liệu, 2- nếu lệnh gọi đang trong quá trình xử lý và 3- hàm thực hiện lệnh gọi tới API.
Rõ ràng, mỗi khi nút được nhấp, toàn bộ thành phần QuoteWrap sẽ được hiển thị lại (dưới dạng quoteData và isLoading thay đổi). Nhưng thực sự, nút không cần phải được hiển thị lại vì nó không bao giờ thay đổi.
Vì vậy, tôi nghĩ: ok, tôi có thể di chuyển nút lên thành phần Ứng dụng. Nhưng sau đó tôi không có quyền truy cập vào chức năng fireNewCall trong hook useQuote.
Làm cách nào để ngăn nút hiển thị lại? Nó thậm chí còn quan trọng trong trường hợp này hay tôi bị ám ảnh bởi các kết xuất React?
Cảm ơn!
Trả lời
Thành phần của bạn sẽ hiển thị lại mỗi khi chức năng handleClick thay đổi, đó là mỗi lần QuoteWrap được hiển thị.
Giải pháp là hook useCallback. useCallback sẽ trả về cùng một hàm cho handleClick, mỗi khi QuoteWrap được hiển thị, miễn là các phần phụ thuộc không thay đổi.
https://reactjs.org/docs/hooks-reference.html#usecallback
Bạn sẽ sử dụng nó như thế này:
const handleClick = useCallback(() => {
fireNewCall();
},[fireNewCall]);
fireNewCall là phần phụ thuộc, vì vậy, miễn là useQuote trả về một hàm fireNewCall ổn định, thì nút của bạn sẽ không hiển thị lại, vì thuộc tính handleClick không thay đổi.
Tôi nghĩ rằng bạn có thể bị ám ảnh bởi các kết xuất React. Nút nên được hiển thị lại bởi vì, handleClicknên được thay đổi khi fireNewCallthay đổi đối với một số trường hợp. Ngay cả khi, handleClicksẽ không bao giờ được thay đổi. Nó không cần phải nghĩ về một phần tử re-render.
Khá nhiều những gì Benjamin và Việt đã nói - trong mã gốc của bạn, một chức năng mới được chỉ định để xử lý Nhấp vào mỗi lần hiển thị. Bạn có thể sử dụng React.useCallbackđể duy trì tham chiếu hàm ban đầu và chỉ cập nhật nó khi một thứ gì đó trong mảng phụ thuộc thay đổi - trong trường hợp này, bạn chỉ fireNewCallcần đi vào mảng phụ thuộc.
Nhưng như Việt nói, đừng quá ám ảnh về nó. Việc sử dụng React.useCallbackthậm chí có thể làm chậm mã của bạn. Kiểm tra Kent C. Dodds Khi nào sử dụngMemo và sử dụng Bài viết gọi lại để biết thêm thông tin chi tiết.