Stale closure: Why did my setState only triggered twice?
Lu Yu
Posted on March 19, 2021
I' trying to build a toast message API for React. My goal is to provide a fireNotification()
api that can be called anywhere in the app and have React render the toast component.
I built this simple notification manager with sub/pub pattern and hope to be able to subscribe to new notifications in a useEffect
hook
const notifications = [];
const listeners = new Set();
function subscribe(callback) {
listeners.add(callback);
}
function publish() {
listeners.forEach((cb) => {
cb(notifications);
});
}
export function fireNotification(content) {
notifications.push(content);
publish();
}
export default function App() {
const [state, setState] = React.useState();
React.useEffect(() => {
subscribe((updated) => {
setState(updated);
});
}, []);
// state will be logged correctly 2 times
// won't be updated after that
console.log("state", state);
return (
<div className="App">
<button onClick={() => {fireNotification('test')}}>fire</button>
</div>
);
}
However, fireNotification()
will only trigger setState
twice
From the 3rd time onward, the state is not updated at all.
I'm able to make state update work by changing setState(updated)
to setState([...updated])
, but not sure why it works.
Can someone explain why setState(updated);
only triggers twice? Thanks!
💖 💪 🙅 🚩
Lu Yu
Posted on March 19, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.