Bạn làm mới trang và màn hình vẫn trống trơn. Hoặc có thể một cú nhấp chuột khiến quạt CPU của bạn chạy hết công suất. Sau đó, console hiển thị cảnh báo đáng sợ: Maximum update depth exceeded. React đã nhấn phanh gấp vì component của bạn đang bị kẹt trong một vòng lặp vô hạn. Đây là một trong những lỗi phổ biến nhất trong các ứng dụng React, và nó thường bắt nguồn từ một sự hiểu lầm đơn giản về thời điểm mã của bạn thực sự chạy.
Để khắc phục, bạn cần hiểu chính xác thời điểm một lần render trở thành một lần re-render, và tại sao các thay đổi về state phải nằm ngoài luồng render.
Cách React Render Component của bạn
Consider this broken pattern:
const UserProfile = () => {
const [user, setUser] = useState({});
useEffect(() => {
setUser({ name: 'Ada', role: 'Admin' });
});
return <div>{user.name}</div>;
};
Because there is no dependency array, this effect runs after every single render. It sets user, which triggers a render. After that render, the effect runs again and sets user again. React detects the spiral and throws the error.
The fix is to tell React when the effect actually needs to run by supplying a proper dependency array. If the effect should only run once on mount, pass an empty array:
useEffect(() => {
setUser({ name: 'Ada', role: 'Admin' });
}, []);
If the effect depends on a prop or a piece of state, include only that variable in the array. Be careful, though. Including a variable that changes every render will just recreate the same loop through a different door. For example, if you include an object literal in the dependencies and that object is recreated on every parent render, the effect will fire endlessly. In those cases, you may need to move the object creation outside the component or memoize it.
Practical Debugging Steps
When you hit this error, the stack trace can look overwhelming because React has already repeated the cycle dozens of times. Start by reading the top of the trace to find which component is named repeatedly. Then look for state setters in these three places:
- The main body of the component, outside any handler or hook.
- JSX event attributes where you might have written
handler()instead ofhandler. useEffecthooks that lack a dependency array or depend on unstable references.
Temporarily comment out each state setter until the error stops. That tells you exactly which update is the culprit. If the setter is inside an effect, ask yourself whether you even need state there. Sometimes developers set local state from props inside an effect when they could simply use the prop directly in the JSX.
The Real Takeaway
The Maximum update depth error is not a mysterious React bug. It is a safety net. It means your component is trying to re-render itself instead of waiting for an external signal. Break the habit of treating renders as events that should produce more state. Treat renders as pure consequences of state, not as causes. Keep state updates inside event handlers, callbacks, or effects with carefully chosen dependencies, and you will never see this error again.
