正常情况下,我们在react hooks中用到最多的就是变量的某种状态的定义以及更改
我们使用input来展示示例
const [name, setName] = useState('aa')
return (
<>
<input value={name} onChange={e => setName(e.target.value)}></input>
<div>My name is {name}</div>
</>
)
这是一个基本的react hooks应用程序,为了开始谈论什么是ref,而不是了解实施的细节,我们想在屏幕上呈现组件渲染的次数,应该怎么做呢?
一、存储渲染次数或者存储不因渲染而重新声明改变的值
我们可以加个div来展示组件渲染的次数,大多数人都想去再定义一些状态变量称为渲染计数,并设置渲染计数
const [renderCount, setRenderCount] = useState(0)
useEffect(() => {
setRenderCount(prevRenderCount => prevRenderCount + 1)
})
<div>I rendered {renderCount} times</div>
但这样有一个巨大的危险就是,当我们更新状态时,导致组件重新渲染,所以我的组件第一次渲染,声明并改变了状态,然后又触发渲染,又重新声明改变状态,这会导致我的组件状态进入无限循环,在无限循环中建立自己……
所以我们这个场景呢就使用ref来解决,因为useRef的值变化是不受渲染所影响的
,不会重新更新
使用ref我们设置它的默认值为1(因为最少会渲染一次)
const renderCount = useRef(0)
它只返回一个对象
,它的结构看起来像这样
renderCount = {current: 0}
renderCount只是具有当前current属性的对象,当我们更新当前对象时,不同的或者多次的渲染都会保留这个属性,
因此在这里我们可以使用它来进行渲染计数
useEffect(() => {
renderCount.current = renderCount.current + 1
})
<div>I rendered {renderCount.current} times</div>
现在我们更改name触发渲染,renderCount的值就会增加
现在我们可以看到,ref值与我们组件的值 是完全分开的~所以我们也可以在其中存储先前的(如上一次渲染的)值 ,并且在这次渲染中用到~
const prevName = useRef('')
useEffect(() => {
// setRenderCount(prevRenderCount => prevRenderCount + 1)
// renderCount.current = renderCount.current + 1
prevName.current = name
})
<div>My name is {name} and it used to be {prevName.current}</div>
二、像文档选择器一样使用
这个应该是我们最常见的ref用法了
const input = useRef(null)
const divText = useRef(null)
divText.current = 'woman'
<input ref={input} value={name}></input>
<div>{divText.current}</div>
<button onClick={() => {
console.log(input)
console.log(input.current)
console.log(input.current.value)
}}>change name</button>
这就相当于我们的文档选择器
- getElementById的用法了
那么有些人可能就非得用ref值 的current去改变这个值 (没错这个人是我~)
<button onClick={() => {
console.log(input)
console.log(input.current)
console.log(input.current.value)
input.current.focus()
input.current.value = 'jerry'
console.log('更新后的inputvalue', input.current.value)
divText.current = 'man'
console.log('更新后的divText', divText.current)
}}>change name</button>
但是我们发现,普通的div是只有值变化了,但是视图没有变化(没有引发渲染所以视图没有变化)
但是改变input元素呢,值不会发生改变 ,但视图可以变化(虽然没有引起渲染但视图也发生变化了),我们只是手动设置了此输入ref的值,这结果是我们不希望看到的,所以建议还是用useState改变状态输入哈~