示例代码及原因
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | import React, { useState } from "react"; /** * 两种写法里,setTimeout 取到的都是旧值,是因为 react 中一直遵循一个原则, * 即 state 指向的内容是不可变的,每一次 state 的更新都是指向变了,而原来指向的内容 * 因为闭包的原因,依然被 setTimeout 使用着,没有释放 * * 所以说 组件的每一次 渲染都是那一瞬间的状态 */ function Example2() { const [count, setCount] = useState(0); function handleAlertClick() { setTimeout(() => { alert("You clicked on: " + count); }, 3000); } return ( <div> <p><center>[wp_ad_camp_1]</center></p><p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}>Click me</button> <button onClick={handleAlertClick}>Show alert</button> </div> ); } class Example extends React.Component { state = { count: 0 }; setCount = count => { this.setState(count); }; handleAlertClick = () => { setTimeout(() => { alert("You clicked on: " + this.state.count); }, 3000); }; render() { return ( <div> <p>You clicked {this.state.count} times</p> <button onClick={() => this.setCount(this.state.count + 1)}> Click me </button> <button onClick={this.handleAlertClick}>Show alert</button> </div> ); } } export default Example; |
解决办法
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | function Example() { const [count, setCount] = useState(0); let ref = useRef(); ref.current = count; function handleAlertClick() { setTimeout(() => { alert("You clicked on: " + ref.current); }, 3000); } return ( <div> <p><center>[wp_ad_camp_2]</center></p><p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}>Click me</button> <button onClick={handleAlertClick}>Show alert</button> </div> ); } |