Trong React, state là bất đồng bộ (asynchronous). Điều này có nghĩa là bạn không nên dựa vào giá trị hiện tại của state nếu bạn muốn cập nhật nó dựa trên giá trị trước đó.
❎️ Sai lầm phổ biến
const [count, setCount] = useState(0); const increase = () => { setCount(count + 1);
};
Vấn đề: Nếu có nhiều lần increase
được gọi liên tiếp (vd: trong loop, event nhanh), count
có thể không được cập nhật đúng vì các lần gọi setCount
đều dùng cùng một giá trị count
cũ.
✅ Cách đúng: Dùng callback của setState
setCount(prevCount => prevCount + 1);
React sẽ đảm bảo prevCount
luôn là giá trị mới nhất, bất kể bạn gọi bao nhiêu lần liên tiếp.
Ví dụ đầy đủ: Counter đơn giản
import React, { useState } from "react"; function Counter() { const [count, setCount] = useState(0); const increase = () => { setCount(prev => prev + 1); }; return ( <div> <p>Count: {count}</p> <button onClick={increase}>+</button> </div> );
}
Mỗi lần nhấn nút, setCount
dùng giá trị trước đó → luôn chính xác.
Khi nào phải dùng giá trị trước đó?
Tình huống | Lý do nên dùng prev => ... |
---|---|
Cập nhật giá trị dạng số | Tránh mất đồng bộ khi có nhiều setState liên tiếp |
Toggling boolean | setShow(prev => !prev) thay vì setShow(!show) |
Thêm item vào mảng | setList(prev => [...prev, newItem]) |
Xoá item khỏi mảng | setList(prev => prev.filter(...)) |
Phụ thuộc vào nhiều state | Tách logic ra để tránh dùng giá trị sai |
Tăng liên tục nhiều lần
const increaseBy3 = () => { setCount(prev => prev + 1); setCount(prev => prev + 1); setCount(prev => prev + 1);
};
👉 Nếu bạn dùng setCount(count + 1)
ba lần, count chỉ tăng 1.
👉 Nhưng với prev => prev + 1
, count sẽ tăng 3, vì mỗi lần đều dùng giá trị mới nhất.
Ngoài ra: Lưu giá trị state cũ (nếu cần so sánh)
Dùng useRef
để lưu lại giá trị trước đó (khác với cách trên – dùng để cập nhật):
import { useEffect, useRef } from "react"; const prevCountRef = useRef(); useEffect(() => { prevCountRef.current = count;
}); const prevCount = prevCountRef.current;
👉 Dùng khi bạn muốn so sánh state hiện tại với state trước đó (ví dụ để trigger animation, logs, v.v.).
🔚 Tổng kết
Trong React, việc cập nhật state thường dựa trên giá trị trước đó, và nếu không làm đúng cách, bạn rất dễ gặp lỗi do state được cập nhật bất đồng bộ. Cách an toàn và đúng chuẩn để lấy giá trị state trước đó là sử dụng hàm callback trong setState
, ví dụ: setCount(prev => prev + 1)
. Cách này đảm bảo bạn luôn làm việc với giá trị mới nhất, tránh sai sót khi gọi setState
nhiều lần liên tiếp hoặc trong các hàm xử lý phức tạp. Ngoài ra, nếu bạn cần so sánh giá trị state hiện tại với giá trị trước đó, hãy dùng useRef
để lưu lại state cũ. Tóm lại, hãy luôn dùng prevState
khi cập nhật state phụ thuộc vào chính nó, và sử dụng useRef
khi cần theo dõi giá trị cũ cho mục đích so sánh hoặc xử lý phụ. Việc hiểu rõ hai kỹ thuật này sẽ giúp bạn viết code React chính xác, ổn định và dễ bảo trì hơn.