为什么 React Hooks useState 更新不符预期?
时间:2022-07-24
本文章向大家介绍为什么 React Hooks useState 更新不符预期?,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
不合预期的更新
在定时器中,用useState
使数字0
做每1
秒递增1
,但结果不合预期:数字增加一次后便不再改变?
- Counter.js
// 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
// 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
指代的是哪一个。
下面两点很重要:
- 在函数式组件中,
state
和prop
都是不可变的 - 函数取到的是本次渲染中内的变量
n
看到的视图有两种状态,也就对应两个渲染状态:
上面两点的意思也就是:在渲染
1
内,n
永远为0
;setN
这个函数取到的n
是0
,设置n+1
永远是1
。
当我们第一次点击按钮时,触发的是渲染1中的函数,这个函数会每隔一秒执行一次setN
,但每次参数都是0+1
如果想要将值置为2
,需要触发渲染2
中的函数才能做到。也就是当视图显示为1
之后,再次去点击按钮。
由于定时器没有清理,可以看到数值在1
和2
间反复交替。
这也验证了渲染1
的定时器只能将值置为1
,渲染2
的定时器只能将值置为2
。
如何使更新符合更新
解决这个问题的方法很简单,即把**useState
里面设置变量的方法里传入一个函数**即可?
setN(n + 1)
改写成setN(n => n + 1)
传入一个函数(setN(n => n + 1)
),是在告诉React
一个指令,下一轮的组件在之前的基础上加一。不用像值作为参数时,关心当前渲染状态下的值具体是多少。
最后
setN(n + 1)
的这种写法并没有问题,如果不用定时器,而是手动点击触发递增,结果也是符合预期的?
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
的参数都是不同的。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Angular @Hostbinding工作原理
- Python干货 | 遥感影像拼接
- SAP Spartacus 自定义指令的实现以及通过@HostBinding实现属性绑定
- Python气象绘图教程—(十九)剖面图
- Angular DefaultDomRenderer2.setProperty
- 在pandas中利用hdf5高效存储数据
- AMS机器学习课程:Keras深度学习 - 卷积神经网络
- python教程 | 最标准的地图调用方式(国家测绘局提供数据)
- 「万物生长」一个APK从诞生到活跃在Android手机上
- webpack实战——生产环境配置【下】
- R语言作图——Violin plot with dot
- AkShare-中国宏观-全社会用电分类情况表
- Angular应用从Component到Html的数据绑定是如何实现的
- 3分钟短文:Laravel Form,让你不再写 HTML 的好“库”
- Angular应用input和div标签页的动态创建场景