jak*_*ndo 3 javascript asynchronous settimeout reactjs
首先,我无法找出这段代码中的问题。但这个问题可能在这里有一席之地。
据我所知,问题可能是单击按钮后计数器值没有更新。尽管在 2.5 秒的延迟期间我单击并增加了计数器的值,但警报会在单击按钮时显示该值。
我是对的吗?如果是的话,这里应该修复或添加什么?
import React, { useState } from 'react'
function Root() {
const [count, setCount] = useState(0)
function handleAlertClick() {
setTimeout(() => {
alert(`You clicked ${count} times`)
}, 2500)
}
return (
<Container>
<Column>
<h4>Closures</h4>
<p>You clicked {count} times</p>
<button type="button" onClick={() => setCount(counter => counter + 1)}>
Click me
</button>
<button type="button" onClick={handleAlertClick}>
Show alert
</button>
</Column>
</Container>
)
}
export default Root
Run Code Online (Sandbox Code Playgroud)
问题
当 被setTimeout调用时,其回调函数将关闭count组件当前渲染中的当前值Root。
在计时器到期之前,如果更新count,会导致组件重新渲染,但回调函数仍会看到调用时有效setTimeout的值。这是由代码中的闭包引起的问题的要点。setTimeout
组件的每个渲染器Root都有自己的状态、道具、组件内部定义的本地函数;简而言之,组件的每个渲染都与其之前的渲染分开。
状态在组件的特定渲染内是恒定的;组件在重新渲染之前无法看到更新后的状态。前一个渲染中设置的任何计时器都会看到它关闭的值;它看不到更新的状态。
解决方案
可以使用useRef钩子来解决由于关闭而导致的问题。
Root您可以在每次重新渲染组件时更新引用。这允许我们保存countref 中的最新值。
一旦有了 ref,就不要传递count给alert,而是传递 ref。这可确保警报始终显示 的最新值count。
function Root() {
const [count, setCount] = React.useState(0)
const countRef = React.useRef(count);
// assign the latest value of "count" to "countRef"
countRef.current = count;
function handleAlertClick() {
setTimeout(() => {
alert(`You clicked ${countRef.current} times`)
}, 2500)
}
return (
<div>
<h4>Closures</h4>
<p>You clicked {count} times</p>
<button type="button" onClick={() => setCount(counter => counter + 1)}>
Click me
</button>
<button type="button" onClick={handleAlertClick}>
Show alert
</button>
</div>
)
}
ReactDOM.render(<Root/>, document.getElementById("root"));Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
870 次 |
| 最近记录: |