Gần nhất là useEffect(() => { ... }, []), nhưng hai thứ không trùng khít: thời điểm chạy khác nhau, và trong Strict Mode ở môi trường phát triển thì số lần chạy cũng khác.
componentDidMount chạy đúng một lần, ngay sau khi component được chèn vào DOM lần đầu — chỗ đặt lời gọi API, đăng ký listener, hoặc khởi tạo thư viện cần DOM sẵn sàng như biểu đồ hay bản đồ.
jsx
// Class
componentDidMount() { this.fetchUser() }
// Function component
useEffect(() => { fetchUser() }, [])Ba chỗ lệch cần biết:
useEffectchạy bất đồng bộ sau khi trình duyệt vẽ xong, còncomponentDidMountchạy đồng bộ trước lượt vẽ. Nếu bạn cần đo kích thước DOM rồi chỉnh layout mà không muốn người dùng thấy nhấp nháy, dùnguseLayoutEffectmới đúng — nó mới là bản khớp về thời điểm.- Strict Mode ở môi trường phát triển thêm một lượt mount → unmount → mount, nên effect chạy hai lần. Class cũng bị y hệt từ React 18 (
componentDidMount→componentWillUnmount→componentDidMount) — nhưng code class thường viết từ thời chưa có hành vi này nên hay không chịu được chạy lại. Chuyển sang hook thì phải viết cleanup cho đúng, không chép nguyên phần thân là xong. - Dependency array rỗng không có nghĩa "chỉ một lần mãi mãi" — component unmount rồi mount lại thì effect chạy lại, giống như
componentDidMountchạy lại ở instance mới.
Lưu ý: Đừng chuyển máy móc từng lifecycle method thành một useEffect riêng. Hook chia theo việc cần đồng bộ, không chia theo thời điểm: một effect lo kết nối, một effect lo tiêu đề trang — thay vì gom hết vào một effect chỉ vì trong class chúng cùng nằm ở componentDidMount.