Nguyên tắc: effect dùng để đồng bộ với hệ thống bên ngoài (WebSocket, DOM API, analytics của bên thứ ba theo vòng đời màn hình). Việc xảy ra vì người dùng làm gì đó thuộc về event handler.
Mẫu sai hay gặp — gửi đơn hàng trong effect khi cờ state bật lên:
jsx
// wrong: submits again on any re-run, hard to reason about
useEffect(() => {
if (submitted) createOrder(cart)
}, [submitted])
// right: it happens because the user clicked
function handleSubmit() {
createOrder(cart)
}Mẫu sai thứ hai — tính giá trị dẫn xuất bằng effect + state:
jsx
// wrong: an extra render pass, state can go out of sync
const [total, setTotal] = useState(0)
useEffect(() => setTotal(items.reduce(sum, 0)), [items])
// right: compute during render
const total = items.reduce(sum, 0)Cách kiểm tra nhanh khi review: nếu bỏ effect đi mà logic vẫn diễn đạt được bằng "khi user bấm X thì làm Y", hoặc bằng một biểu thức tính trong render, thì effect đó thừa.
Effect thừa gây thêm một vòng render, và với các thao tác ghi (POST, thanh toán) còn dễ chạy hai lần.