前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >为什么 React Hooks useState 更新不符预期?

为什么 React Hooks useState 更新不符预期?

作者头像
前端老王
发布2020-09-14 11:27:18
1.6K0
发布2020-09-14 11:27:18
举报
文章被收录于专栏:前端时空前端时空

不合预期的更新

在定时器中,用useState使数字0做每1秒递增1,但结果不合预期:数字增加一次后便不再改变?

  • Counter.js
代码语言:javascript
复制
// Counter.js
import React, { useState } from 'react'
import './Counter.css'

function IntervalCounter() {
  const [n, setN] = useState(0)
  function autoIncrease() {
    setInterval(() => {
      setN(n + 1) // 只增加一次
    }, 1000)
  }
  return (
    <div className='AppOne'>
      <p>{n}</p>
      <p>
        <button onClick={() => autoIncrease()}>Set Interval To Increase</button>
      </p>
    </div>
  )
}

export default { IntervalCounter }
  • index.js
代码语言:javascript
复制
// index.js
import React from 'react'
import ReactDOM from 'react-dom'
import Counter from './Counter'

ReactDOM.render(
  <React.StrictMode>
    <Counter.IntervalCounter></Counter.IntervalCounter>
  </React.StrictMode>,
  document.getElementById('root')
)

要弄清为什么setN(n + 1)没有生效,要先了解传入的参数值代表了什么含义。当我们传入n+1,是在告诉React,下一轮的渲染按照我给的值。因为n是一个变量,所以要确定下来这个变量到底是多少,即n指代的是哪一个。

下面两点很重要:

  • 在函数式组件中,stateprop都是不可变
  • 函数取到的是本次渲染中内的变量n

看到的视图有两种状态,也就对应两个渲染状态:

上面两点的意思也就是:在渲染1内,n永远为0setN这个函数取到的n0,设置n+1永远是1

当我们第一次点击按钮时,触发的是渲染1中的函数,这个函数会每隔一秒执行一次setN,但每次参数都是0+1

如果想要将值置为2,需要触发渲染2中的函数才能做到。也就是当视图显示为1之后,再次去点击按钮。

由于定时器没有清理,可以看到数值在12间反复交替。

这也验证了渲染1的定时器只能将值置为1,渲染2的定时器只能将值置为2

如何使更新符合更新

解决这个问题的方法很简单,即把**useState里面设置变量的方法里传入一个函数**即可?

setN(n + 1)改写成setN(n => n + 1)

传入一个函数setN(n => n + 1)),是在告诉React一个指令,下一轮的组件在之前的基础上加一。不用像值作为参数时,关心当前渲染状态下的值具体是多少

最后

setN(n + 1)的这种写法并没有问题,如果不用定时器,而是手动点击触发递增,结果也是符合预期的?

代码语言:javascript
复制
function SimpleCounter() {
  const [n, setN] = useState(0)
  function handleClick() {
    setN(n + 1)
  }
  return (
    <div className='AppOne'>
      <p>{n}</p>
      <p>
        <button onClick={() => handleClick()}>Click +1</button>
      </p>
    </div>
  )
}

三次点击触发的是三个渲染内的三个函数,每一个函数内setN的参数都是不同的。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-09-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端时空 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 不合预期的更新
  • 如何使更新符合更新
  • 最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档