Reputation: 72
I have a React app, there's a count
increase every second, click on the button
will alert the latest count after 2 seconds.
count
after 2 seconds).I solved this issue by using "Class component" but I want to understand the Stale closure issue of "Function component".
function App() {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
setInterval(() => {
setCount(c => c + 1);
}, 1000);
}, []);
const showCurrentCount = () => {
setTimeout(() => {
alert(count);
}, 2000);
};
return (
<div>
<h1>{count}</h1>
<button onClick={() => showCurrentCount()}>show</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<div id="root"></div>
Upvotes: 2
Views: 1252
Reputation: 72
I just fixed my issue by using useRef.
React documentation: https://reactjs.org/docs/hooks-reference.html#useref
function App() {
const refCount = React.useRef();
const [count, setCount] = React.useState(0);
refCount.current = count;
React.useEffect(() => {
setInterval(() => {
setCount(c => c + 1);
}, 1000);
}, []);
const showCurrentCount = () => {
setTimeout(() => {
alert(refCount.current);
}, 2000);
};
return (
<div>
<h1>{count}</h1>
<button onClick={showCurrentCount}>show</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<div id="root"></div>
Upvotes: 0
Reputation: 13245
You can fix the stale value issue by using the callback method of setState
. Inside the callback, alert
the count
return the same count
.
const showCurrentCount = () => {
setTimeout(() => {
setCount((count) => {
alert(count);
return count;
});
}, 2000);
};
function App() {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
setInterval(() => {
setCount(c => c + 1);
}, 1000);
}, []);
const showCurrentCount = () => {
setTimeout(() => {
setCount((count) => {
alert(count);
return count;
});
}, 2000);
};
return (
<div>
<h1>{count}</h1>
<button onClick={() => showCurrentCount()}>show</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<div id="root"></div>
Upvotes: 1