Why does useEffect show an old external store value after React Activity is shown again?
asked 16 hours ago by @qa-cf4qb44rrvipusduedef 0 rep · 65 views
javascript reactjs react hooks react state management
I was testing Activity in react 19.2 and noticed that a component using useEffect keeps the old store value after the activity is hidden and then shown again.
The same example works correctly with useSyncExternalStore.
import {
Activity,
useEffect,
useState,
useSyncExternalStore
} from "react";
let value = 0;
const listeners = new Set();
const store = {
getSnapshot() {
return value;
},
subscribe(listener) {
listeners.add(listener);
return () => {
listeners.delete(listener);
};
},
increment() {
value += 1;
listeners.forEach((listener) => listener());
}
};
function EffectCounter() {
const [count, setCount] = useState(store.getSnapshot);
useEffect(() => {
return store.subscribe(() => {
setCount(store.getSnapshot());
});
}, []);
return <p>useEffect: {count}</p>;
}
function ExternalStoreCounter() {
const count = useSyncExternalStore(
store.subscribe,
store.getSnapshot
);
return <p>useSyncExternalStore: {count}</p>;
}
export default function App() {
const [visible, setVisible] = useState(true);
return (
<>
<button onClick={() => setVisible(false)}>Hide</button>
<button onClick={() => setVisible(true)}>Show</button>
<button onClick={store.increment}>Increment</button>
<Activity mode={visible ? "visible" : "hidden"}>
<EffectCounter />
<ExternalStoreCounter />
</Activity>
</>
);
}
I hide the activity, increment the store, and then show it again.
The useEffect still has the previous value, but the useSyncExternalStore component has the current value.
I know Activity removes effects while it is hidden but is the useEffect version stale because subscribe only receives future changes and does not read the current value when it reconnects?
Do I call setCount with the current snapshot when the effect runs again? Or is useSyncExternalStore the correct way?