Quy tắc phân biệt: giá trị nào hiển thị ra UI thì dùng state; giá trị chỉ để ghi nhớ giữa các lần render thì dùng ref.
useState | useRef | |
|---|---|---|
| Gán giá trị mới | gọi setter, gây re-render | gán ref.current, không re-render |
| Đọc trong render | luôn hợp lệ | không nên đọc/ghi khi đang render |
| Dùng cho | dữ liệu hiển thị | id timer, DOM node, cờ nội bộ |
jsx
const timerId = useRef(null) // no re-render needed
const [seconds, setSeconds] = useState(0) // shown on screen
function start() {
timerId.current = setInterval(() => setSeconds((s) => s + 1), 1000)
}
function stop() {
clearInterval(timerId.current)
}Nếu để timerId trong state, mỗi lần start/stop lại kích hoạt một lần render vô ích. Ngược lại, nếu để seconds trong ref thì màn hình đứng yên vì React không biết có gì thay đổi.
Các trường hợp ref hay dùng: giữ DOM node (inputRef.current.focus()), lưu id của setTimeout/setInterval, lưu giá trị lần render trước, và giữ instance của thư viện bên thứ ba.