useState在函数中多次使用后无法正常工作

时间:2019-08-09 16:50:00

标签: reactjs react-hooks

我的功能很简单:

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 的值不同。

为什么从功能内部读取状态,即使更改状态后,控制台日志也会显示初始值?

我认为这是异步/等待问题,但不是。我几乎完成了相同的同步,结果也相同。

1 个答案:

答案 0 :(得分:0)

重要的是要记住,每次渲染组件时,都会读取countercounter2的当前值,并且这些值在组件再次渲染之前不会改变。因此,组件首次渲染时,countercounter2均为0

类似地,将创建realizePayment的新副本,该副本通过闭合保留countercounter2的特定版本。因此,无论调用多少次,第一个渲染器的realizePaymentcountercounter2的版本都仍为0。

  1. 为什么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变量。

  1. 为什么它们在功能结束时记录的内容与开始时相同?

同样,对于给定版本的realizePayment,两个变量都不会更改,因此,它们始终在函数末尾记录与开始相同的值。

  1. 为什么即使在状态更新后,它们在realizePayment的开头始终始终为0?

您的示例代码尚不清楚如何调用realizePayment:按照书面规定,这不是合法的JS,您是从组件外部调用组件内部定义的函数。

但是请记住,组件的每个渲染都会产生realizePayment函数的新副本,其中包含countercounter2的特定值。根据您的日志,您总是在调用相同版本的realizePayment,即初始渲染中的版本。