React Hooks的useRef

154 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 15天,点击查看活动详情

useRef是什么

它是react的一个hooks,用来做一些state不太方便做的事,同时也可以用来获取到dom对象. 那么它有什么特点呢?

  • useRef对象返回一个可变的ref对象,同时只有一个current属性,可以传入一个初始值.
  • 可变的ref对象在整个生命周期中是保持不变的,不像state那样会导致组件的重复渲染,而 useState 更新值时会触发页面渲染.
  • 更新 useRef 是 side effect (副作用),所以一般写在 useEffect 或 event handler 里.

useRef主要用途

可以用来实时保存上一次的值

要知道useState是异步更新的,不能同步获取到值,只能在useEffect中获取到更新后的值,但是useRef可以拿到最新的值,且不会触发组件的重新渲染.

function usePrevious(value) {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  });
  return ref.current;
}

做一个定时器

即使useState发生变化导致组件重新渲染,ref的值也还是上次的值.所以我们可以用来在组件中保存一些不需要经常变化的值,因此我们可以来做一个定时器.

const App = () => {
  let timer;
  useEffect(() => {
    timer = setInterval(() => {
      console.log('触发了');
    }, 1000);
  },[]);
  const clearTimer = () => {
    clearInterval(timer);
  }
  return (
    <>
      <Button onClick={clearTimer}>停止</Button>
    </>)
}

获取子组件的属性和方法

import React, {MutableRefObject, useState, useEffect, useRef, useCallback} from 'react'
interface IProps {
    //prettier-ignore
    label: string,
    cRef: MutableRefObject<any>
}
const ChildInput: React.FC<IProps> = (props) => {
    const { label, cRef } = props
    const [value, setValue] = useState('')
    const handleChange = (e: any) => {
        const value = e.target.value
        setValue(value)
    }
    const getValue = useCallback(() => {
        return value
    }, [value])
    useEffect(() => {
        if (cRef && cRef.current) {
            cRef.current.getValue = getValue
        }
    }, [getValue])
    return (
        <div>
            <span>{label}:</span>
            <input type="text" value={value} onChange={handleChange} />
        </div>
    )
}
const ParentCom: React.FC = (props: any) => {
    const childRef: MutableRefObject<any> = useRef({})
    const handleFocus = () => {
        const node = childRef.current
        alert(node.getValue())
    }
    return (
        <div>
            <ChildInput label={'名称'} cRef={childRef} />
            <button onClick={handleFocus}>focus</button>
        </div>
    )
}
export default ParentCom

像这样我们便可以去获取到子组件的属性和方法.

结尾

  • 不同组件之间和同一个组件被多次使用,ref也是不同的.
  • 组件重新渲染之后,全局变量会被重新创建,ref 则不会被刷新。