+10

Lấy giá trị state trước đó trong React như thế nào cho đúng và tránh lỗi

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á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.


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.