React chạy theo hai lượt tách rời trong giai đoạn commit:
1. Toàn bộ cleanup trước, theo thứ tự con trước cha.
2. Rồi mới tới toàn bộ setup, cũng theo thứ tự con trước cha.
Nghĩa là cleanup của cha đã chạy xong trước khi setup của con bắt đầu. React không xen kẽ cleanup–setup theo từng component.
Hệ quả thực tế:
- Không được giả định rằng khi cleanup của con chạy thì tài nguyên của cha vẫn còn — cleanup phải tự đủ, không phụ thuộc thứ tự với component khác.
- Effect của con chạy trước effect của cha, nên nếu cha cần đo đạc dựa trên việc con đã setup xong thì thứ tự này là đúng.
- Cleanup nhận được giá trị của lần render trước (closure của lượt setup tương ứng), nên huỷ đúng thứ đã đăng ký chứ không phải thứ mới nhất:
jsx
useEffect(() => {
const conn = createConnection(roomId) // roomId of this render
conn.connect()
return () => conn.disconnect() // disconnects that same conn
}, [roomId])Riêng useLayoutEffect chạy trọn cả hai lượt trước khi trình duyệt vẽ, còn useEffect chạy sau khi vẽ — nên hai loại này không xen lẫn nhau về thời điểm.