React-useRef

useRef

useRef 是一个 React Hook,它能帮助引用一个不需要渲染的值。

使用方式

const ref = useRef(initialValue)

传入的参数是一个初始值initialValue,也是ref的current属性的初始值。这个值可以是任意类型的值。

返回值是一个只有一个属性current的对象,current的初始值就是传入的initialValue。

注意事项:

  • ref.current属性值可以更改,并且修改ref.current属性值不会触发渲染。
  • 除了初始化渲染外,不要在渲染期间读取和写入(修改)ref.current的值。可以在 事件处理程序或者 Effect 中读取和写入 ref.current
  • 也就是说,ref.current可以用来存储一些不影响组件渲染和视图的值,以及一些需要长久留存在组件中的值。

在多次渲染中保持对一个变量的相同引用

React的每一次渲染都像是生成一张快照,也就是说每次渲染函数都拥有自己内部独立的props和state。当触发setState函数的时候,就会触发一次渲染,生成一张新的快照,渲染函数内部就会出现新的props和state。这个时候。哪怕是在渲染函数内部定义的变量,也会用新的引用,也就是Object.is会判断为false。

import { useState } from "react"

const UseStateDemo = () => {
  const [count, setCount] = useState(0)
  const [msg, setMsg] = useState('msg')

  const handleClick = () => {
    console.log('count', count) // 0

    setCount(count + 1); // 请求使用 1 重新渲染
    console.log(count);  // 仍然是 0!

    let timer = setTimeout(() => {
      clearTimeout(timer)
      console.log('setTimeout', count); // 还是 0!
    }, 5000);
  }

  return (
    <div>
      <div>{msg}-count: {count}</div>
      <div>
        <button onClick={handleClick}>add</button>
      </div>
    </div>
  )
}

export default UseStateDemo

这也是因为倒计时函数会打印出 0 的原因。当我们第一次调用函数UseStateDemo的时候,count的值为 0 。当触发setCount的时候,react就会拿着新的count值重新渲染,也就是重新调用函数UseStateDemo。而每次渲染中的count的值是独立的,同时并不会影响正在执行的事件处理函数。所以在第一次渲染中,执行的倒计时函数中count的值仍然为 0 。

如果我们想要在倒计时函数中就能拿到最新的 count 值,或者说拿到变化后的 count 值。就可以借助 useRef

import { useState, useRef } from "react"

export default function UseRefDemo () {
  const [count, setCount] = useState(0)
  const countRef = useRef(1)

  const handleClick = () => {
    setCount(count + 1)
    countRef.current = countRef.current + 1
    console.log('count', count)  // 仍然是 0!
    console.log('countRef.current', countRef.current)  // 变为 1 
  
  }

  return (
    <div>
      <div>count: {count}</div>
      {/* <div>countRef: {countRef.current}</div>  */}
      {/** useRef.current 可以参与渲染;但是不要让useRef在渲染期间读取或写入 */}
      <div>
        <button onClick={handleClick}>add</button>
      </div>
    </div>
  )
}

所以useRef还可以用来保存定时器,方便后续不需要的时候销毁定时器。

import { useState, useRef } from "react"

export default function UseRefDemo () {
  const [count, setCount] = useState(0)
  const countRef = useRef(1)
  const setTimeRef = useRef(null)

  const handleClick = () => {
    setCount(count + 1)
    countRef.current = countRef.current + 1
    console.log('count', count)  // 仍然是 0!
    console.log('countRef.current', countRef.current)  // 变为 1 
    const intervalId = setInterval(() => {
        console.log('setInterval')
    }, 1000)
  }
  
  const handleStopClick = () => {
      const intervalId = setTimeRef.current
      clearInterval(intervalId)
  }

  return (
    <div>
      <div>count: {count}</div>
      {/* <div>countRef: {countRef.current}</div>  */}
      {/** useRef.current 可以参与渲染;但是不要让useRef在渲染期间读取或写入 */}
      <div>
        <button onClick={handleClick}>add</button>
          <button onClick={handleStopClick}>stop</button>
      </div>
    </div>
  )
}

通过useRef来操作DOM

在vue3中是通过ref来获取DOM元素的

<template>
  <div>
      <input ref="inputRef" type="text" />
  </div>
  <button @click="onFocus">
      focus
  </button>
</template>
<script setup>
import { ref } from 'vue'
const inputRef = ref(null)
const onFocus = () => {
    inputRef.value.focus()
}

</script>

在react中,也可以通过 useRef 来获取DOM元素。

import { useState, useRef } from "react"

export default function UseRefDemo () {
  const inputRef = useRef(null)
  const onFocus = () => {
      inputRef.current.focus();
  }

  return (
 	<div>
  		<input ref="inputRef" type="text" />
  	</div>
  	<button @click="onFocus">focus</button>
  )
}
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值