我的功能很简单:
const payForCheckedOrders = () => {await realizePayment()};
const Test = () => {
const [counter, setCounter] = useState(0);
const [counter2, setCounter2] = useState(0);
console.log('render', counter, counter2);
const realizePayment = async () => {
for (let i = 0; i < 3; i++) {
console.log('func start', counter, counter2);
setCounter(counter + 1);
setCounter2(prev => prev + 1);
console.log('func end', counter, counter2);
await sleep(500);
}
};
}
重要的事实是当我调用函数时,结果是:
func start 0 0
func end 0 0
渲染1 1
func start 0 0
渲染1 1
渲染1 2
func end 0 0
func start 0 0
渲染1 2
渲染1 3
func end 0 0
我的问题是,为什么呈现控制台日志中的 counter 与 counter2 的值不同。
为什么从功能内部读取状态,即使更改状态后,控制台日志也会显示初始值?
我认为这是异步/等待问题,但不是。我几乎完成了相同的同步,结果也相同。
答案 0 :(得分:0)
重要的是要记住,每次渲染组件时,都会读取counter
和counter2
的当前值,并且这些值在组件再次渲染之前不会改变。因此,组件首次渲染时,counter
和counter2
均为0
。
类似地,将创建realizePayment
的新副本,该副本通过闭合保留counter
和counter2
的特定版本。因此,无论调用多少次,第一个渲染器的realizePayment
,counter
和counter2
的版本都仍为0。
counter2
没有增加,counter
却增加了? 由于counter
设置为setCounter(counter + 1)
,而counter2
设置为setCounter2(prev => prev + 1)
:由于counter
变量不变,因此counter + 1
对于realizePayment
的给定版本,它总是相同的。对于第一个渲染器的版本,counter
为0,因此它多次执行setCounter(1)
。 (因此,为什么在随后的渲染中始终总是1
。
另一方面,prev => prev + 1
使用的setCounter2
版本读取当前值,而不是依赖不变的counter2
变量。
同样,对于给定版本的realizePayment
,两个变量都不会更改,因此,它们始终在函数末尾记录与开始相同的值。
realizePayment
的开头始终始终为0?您的示例代码尚不清楚如何调用realizePayment
:按照书面规定,这不是合法的JS,您是从组件外部调用组件内部定义的函数。
但是请记住,组件的每个渲染都会产生realizePayment
函数的新副本,其中包含counter
和counter2
的特定值。根据您的日志,您总是在调用相同版本的realizePayment
,即初始渲染中的版本。