Vì được yêu thích nên hôm nay lại là chủ đề về hooks thôi, hy vọng không ai thất vọng với điều này.
useEffect(effect, deps)
Khái niệm
Bằng một vài cách nào đó, bạn có thể tìm được khái niệm useEffect
là:
The
useEffect
Hook allows you to perform side effects in your components.
Chức năng
Khái niệm thật sự khó hiểu đúng không nào, để nói thì useEffect
thật sự sẽ thay thế cho componentDidMount
, componentDidUpdate
, và componentWillUnmount
.
Ví dụ
Vấn với ví dụ thường ngày vì mình quá lười =)))
1 | import { useState, useEffect, useRef } from "react"; |
componentDidMount
Đây là cách dùng đơn giản nhất của useEffect
với deps của chúng ta là []
, khi này thì useEffect
của chúng ta chỉ chạy đúng một lần khi did mount:
1 | useEffect(() => { |
Như bạn thấy, ở ví dụ thì dù bạn có bấm random để re-render bao nhiêu lần đi nữa thì ref.current mà nó chỉ lấy giá trị lúc mount của randomID1 là 1 mà thôi, cũng không thay đổi một lần nào nữa vì lúc này useEffect
không chạy khi update mà chỉ chạy khi mount.
componentDidUpdate
Khi chúng ta không truyền tham số vào, tức là lúc này deps
ở đây của chúng ta có giá trị là undefined
và useEffect
sẽ hoạt động như là componentDidUpdate, sẽ chạy sau bất cứ khi nào component re-render (did update)
1 | useEffect(() => { |
Hoặc truyền vào state mà bạn muốn nó chạy mỗi khi thay đổi giống như hình dưới.
1 | useEffect(() => { |
Như bạn thấy, mỗi khi mình bấm setRandomID1 thì nó đều thay đổi vì current luôn liên tục được set giá trị của randomID1.
componentDidMount(effect => cleanup, deps)
1 | useEffect(() => { |
bạn chỉ cần return về một function và nó sẽ trở thành componentUnMount rồi, mình không thể cap hình vì mình quá lười nhưng bạn có thể xem nó ở đây nè: https://stackoverflow.com/a/55020668
useLayoutEffect(effect, deps)
Hehe, useEffect
là một cái gì đó mà rất thông thường rồi nên mình rất lười khi viết nó, useLayoutEffect
lại là một vấn đề khác, cách sử dụng của nó khá tương tự với useEffect
và mọi người thường hay tự hỏi khi đọc được nó là nó xuất hiện để làm gì =))
Khái niệm
Bằng một vài bước google thì trang chủ nó có khái niệm là:
The signature is identical to
useEffect
, but it fires synchronously after all DOM mutations. Use this to read layout from the DOM and synchronously re-render. Updates scheduled insideuseLayoutEffect
will be flushed synchronously, before the browser has a chance to paint.
Prefer the standarduseEffect
when possible to avoid blocking visual updates.
Chức năng
Tương tự useEffect
thì useLayoutEffect
lấy một function được gọi là effect làm đối số đầu tiên, và một mảng phụ thuộc làm đối số thứ hai. Đối số đầu tiên, effect, trả về một cleanup function hoặc giá trị undefined . useLayoutEffect
được minh hoạ như code dưới đây
Ví dụ
Giống hệt như trên luôn, chỉ khá là các bạn ctrl + H
và replace useEffect
sang useLayoutEffect
và mọi thứ hoạt động hoàn hảo không sai một tí nào, và… nó xuất hiện làm gì nhỉ?
So sánh giữa useEffect
với useLayoutEffect
Tất nhiên team facebook không rảnh để tạo ra một function mới có chức năng giống hệt mà chỉ đổi tên thôi đúng không nào, useEffect
và useLayoutEffect
có 2 điểm khác nhau lớn nhất và chí mạng là:
1. Thời điểm thực thi effect:
Với useEffect
, thì trình tự thực thi sẽ là:
- Bạn gây ra một sự kiện re-render.
- React re-render component của bạn.
- Màn hình được cập nhật giao diện.
- Cuối cùng
useEffect
chạy một cách bất đồng bộ.
Còn với useLayoutEffect
thì:
- Bạn gây ra một sự kiện re-render.
- React re-render component của bạn.
- Cuối cùng
useLayoutEffect
chạy đồng bộ, khi nào xong thì step tiếp mới được thực thi. - Màn hình được cập nhật giao diện.
2. Bất đồng bộ và đồng bộ:
Bạn thấy ngay keyword rồi đấy, useLayoutEffect
sẽ chỉ được thực thi đồng bộ và khi nào nó thực thi xong UI mới được cập nhật đúng không nào. Điều này khiến cho trong một số trường hợp nó giải quyết được vấn đề giá trị state thay đổi khiến cho dữ liệu màn hình nhấp nháy rất khó chịu. Và thường thì nó sinh ra chỉ để giải quyết vấn đề này. Bạn xem gif bên dưới để hiểu thêm nhé
Với useEffect
:
Bạn có thấy mấy số random nó nháy nháy từ giá trị default sang giá trị mới rất khó chịu đúng không nào.
Chỉ cần ctrl + H
và replace useEffect
sang useLayoutEffect
thì:
Cảm giác nhấp nháy khó chịu đó đã biến mất hoàn toàn, thay vào đó thì tốc độ hình ảnh xuất hiện có chậm hơn một tí nhưng mình nghĩ đây không phải vấn đề trong trường hợp này.
Kết luận
Aizz, nếu có ai đó hỏi mình là nên dùng useEffect
hay useLayoutEffect
thì phần lớn câu trả lời của mình là useEffect
, bởi vì useLayoutEffect
là đồng bộ và app của bạn sẽ không hiển thị gì cả đến khi effect hoàn thành và nó có thể và chắc chắn có thể là nguyên nhân xảy ra vấn đề về performance nếu bạn có những đoạn code xử lý chậm trong effect.