不会弹吉他的铁匠不是一名好铁匠!大家好,我是拿吉他的铁匠,码字不易,希望大家多多点赞。
这篇文章主要是用来整理React中的useState和useRef的使用以及使用场景;在React中,分为类组件和函数组件,类组件是有自己的状态以及生命周期,函数组件是没有状态和生命周期的,所以在函数组件中,可以使用React提供的use Hooks添加状态,以及模块生命周期;useState和useRef就是用来在函数组件中添加状态。
UseRef
声明状态:
首先是引入useState:
import React, { useState } from "react";
-
useState一次只能声明一个状态变量,这个状态变量可以是任意类型的;
-
useState接收一个参数作为初始值,会在第一次渲染的时候被使用;
-
useState返回一个数组,通常会以数组解构的方式使用:
- const [count, setCount] = useState(0)
- count 是状态变量;setCount是改变该状态变量的方法;
更新状态
传入固定值:
- const addCount = () => { setCount(10) }
想要在旧值的基础上得到新值,可以使用函数的形式:
- const addCount = () => { setCount(count => count + 1) }
每一次更新状态,都会触发render重新渲染当前的组件;因此在涉及到对组件的操作时,使用useState是非常合适的;
注意点
-
useState()的异步性:
- 在useState()更新状态后,马上获取state的值,会发现获取的不是最新值;这是因为React更新state的值是异步更新的:
const addCount = () => { setCount(count => count + 1) // 3 submit() } const submit = () => { console.log(count) // 2 }正如上面的更新状态,页面上更新为3,但是获取count还是上次的旧值;所以想要马上使用state的最新值,useState()显然不能满足我们的需求;
-
在顶层调用useState;
-
useState()不能在类组件中使用;
-
不能在条件,循环,内嵌方法中使用useState,因为React依赖于useState函数被调用的顺序来获取特定变量的正确值;
useRef
获取DOM元素或者组件实例
// 引入
import React, { useState, useRef } from "react"
// 声明
const domRef = useRef(null)
// 赋值给DOM元素的ref属性
<button onClick={addCount} ref={domRef}>改变</button>
// 使用
const addCount = () => {
console.log(domRef.current.innerHTML)
}
这是useRef()的传统用法,通过对象的current属性就能获取到DOM元素;
获取状态的最新值
上面useState()无法获取最新值,在这里可以通过useRef()来解决这个棘手的问题;
useRef()返回一个可变Ref对象,包含一个current属性,返回的ref对象在整个生命周期内保持不变;
可以改变ref对象的current属性,不会触发组件的重新渲染;
通过ref对象的current属性获取变量的最新值;
const countRef = useRef(0)
const addCount = () => {
let d = Math.random()
setCount(d)
countRef.current = d
submit()
}
const submit = () => {
console.log(countRef.current)
}
在变量每次更新的时候,将最新的变量值保存在countRef的current属性中,在submit函数中就能得到变量的最新值;
上面代码是直接将传值保存在current属性中,现在不传值,想要实时获取setCount变化的值,又该怎么做呢?
import React, { useState, useRef, useEffect } from "react"
const countRef = useRef(0)
useEffect(() => {
countRef.current = count
}, [count])
const addCount = () => {
setCount(d => d + 1)
// countRef.current = count 这里保存的仍然是旧值,不正确
// 这里非常重要
setTimeout(submit, 0)
}
const submit = () => {
console.log(countRef.current)
}
上面的案例中,是count每次点击加1,还在addCount中保存到current,保存的是旧值,并不是最新值;这里就用到useEffect;
useEffect相当于类组件的生命周期钩子,会监听第二个参数值的变化,一旦监听到变化,就会执行回调;
上述的案例的步骤如下:
- setCount会更新count值的变化,会触发render重新渲染组件;
- useEffect()钩子监听到count值的变化,会将当前最新值保存在ref对象的current属性上;
- 使用定时器来调用submit方法,这样也将submit转变为异步调用,确保在useEffect()执行完毕后获取到最新值;
所以简单总结一下:
- 涉及到组件渲染更新可以使用useState();
- 涉及到实时获取最新值,可以使用useRef();