Trong React, chúng ta có 2 cách để chạy các side-effect là: useEffectuseLayoutEffect

Sự khác nhau giữa hai hàm này không lớn lắm, và 99% thời gian chúng ta chỉ cần sử dụng useEffect là có thể giải quyết định các side-effect. Nhưng trong một số trường hợp useLayoutEffect vẫn rất hữu ích.

Xem chi tiết sự khác nhau giữa hai hàm này này tại bài viết của Kent C.Dodds. Hay tham khảo chi tiết react hooks flow

Vậy useLayoutEffect được sử dụng khi nào? Hay khác hơn là tại sao phải sử dụng useLayoutEffect? Sau đây là một demo, khi bạn click vào nút “add message” thì scroll sẽ bị delay khoảng 1s đúng không? Điều chúng ta muốn ở đây là khi thêm một message thì scroll sẽ chạy mượt mà hơn, không còn hiện tượng bị delay hay giựt giựt nữa.

React.useEffect(() => {
    containerRef.current.scrollTop = containerRef.current.scrollHeight
})

Chúng ta có thể sử dụng useLayoutEffect để tránh được hiện tượng này:

React.useLayoutEffect(() => {
    containerRef.current.scrollTop = containerRef.current.scrollHeight
})

Kết quả sau khi sử dụng useLayoutEffect bạn có thể tham khảo tại đây.

useLayoutEffect sẽ chạy trước khi DOM được vẽ lên màn hình cho nên nó có thể can thiệp sớm và set scrollTop, dẫn tới scroll được mượt mà hơn. Bạn có thể nhận thấy điều đó trong diagram sau:

 

Vậy nên sử dụngEffect hay sử dụngLayoutEffect?
Trong hầu hết các trường hợp, useEffect là lựa chọn phù hợp. Nếu code của bạn gây hiện tượng nhấp nháy, hay thử chuyển sang dùng useLayoutEffect xem có khắc phục được không?

Vì useLayoutEffect là động bộ chặn, ứng dụng sẽ không cập nhật giao diện cho đến khi code của bạn chạy xong, nên có thể gây ra một số vấn đề về hiệu suất nếu như có đoạn code làm chậm quá trình chương trình chạy.

Nếu mã của bạn gây ra hiện tượng nhấp nháy, hãy chuyển sang useLayoutEffect và xem điều đó có hữu ích không.

Vì useLayoutEffect là đồng bộ chặn ứng dụng sẽ không cập nhật giao diện cho đến khi hiệu ứng của bạn chạy xong… nên có thể gây ra các vấn đề về hiệu suất như nói lắp nếu bạn có mã chậm. Thực tế là hầu hết các trường hợp không cần thiết phải tạm dừng trong khi chạy, nên việc sử dụng useEffect là đáp ứng đủ.