useRef

1、访问 DOM 节点

import { useRef } from 'react'

export default () => {
    const inputElement = useRef(null)
    
    const handleClick = () => {
        inputElement.current.focus()
    }
    
    return {
        <>
            <input ref={inputElement} type="text" />
            <button onClick={handleClick}>foucs input</button>
        </>
    }
}

2、useRef 用来跨越渲染周期存储数据,而且对它修改也不会引起组件渲染

useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组建的整个生命周期内保持不变。

import React, { useState, useRef } from 'react'

export default () => {

  const [period, setPeriod] = useState(selectedPeriod)
  const [subject, setSubject] = useState(selectedSubject)
  const [periodList, setPeriodList] = useState([])
  const [subjectList, setSubjectList] = useState([])

  // 缓存科目
  const subjectRef = useRef(subject)
  useEffect(() => { subjectRef.current = subject }, [subject])

  useEffect(() => {
    setPeriod(selectedPeriod)
    setSubject(selectedSubject)
  }, [selectedPeriod, selectedSubject])

  // 学段列表
  useEffect(() => {
    (async () => {
      const periodList = await onGetPeriodList()
      setPeriodList(periodList)
    })()
  }, [onGetPeriodList])

  // 切换学段要重新获取对应的科目
  useEffect(() => {
    (async () => {
      const subjectList = await onGetSubjectList(period)
      setSubjectList(subjectList)
      // 这里用 useRef 缓存切换学段前选中的科目,在改变后,如果有相同的科目,就默认选中,否则选中第一个
      // 这里不能直接使用 subject 的原因是:使用 subject,就要添加 subject 作为依赖,在调用setSubject 的时候会导致死循环
      const { current: subjectCache } = subjectRef
      const defaultSubject = subjectList.find((subject) => subject.id === subjectCache.id) || subjectList[0]
      setSubject(defaultSubject)
    })()
  }, [period, onGetSubjectList])
}

3、useRef 和 createRef 的区别

reateRef 每次渲染都会返回一个新的引用,而 useRef 每次都会返回相同的引用。

import React, { useState, useRef } from 'react'

export default () => {
    const [renderIndex, setRenderIndex] = useState(1)
    const useRefDom = useRef()
    const createRefDom = createRef()

    if (!useRefDom.current) {
        useRefFDom.current = renderIndex    
    }
    if (!createRefDom.current) {
        createRefDom.current = renderIndex    
    }

    return (
        <>
            <p>current render index: { renderIndex }</p>
            <p>useRefDom: {useRefDom.current}</p>
            <p>createRefDom: {createRefDom.current}</p>
            <button onClick={setRenderIndex(prev => prev + 1)}>
                cause re-render
            </button>
        </>
    )
}

4、小结

  • useRef 是一个方法,且 useRef 返回一个可变的ref对象(对象!!!);
  • initialValue 被赋值给其返回值的 .current 对象;
  • ref 对象与自建一个 { current:'' } 对象的区别是:useRef 会在每次渲染时返回同一个 ref 对象,即返回的 ref 对象在组件的整个生命周期内保持不变。自建对象每次渲染时都建立一个新的。
  • ref 对象的值发生改变之后,不会触发组件重新渲染。
  • 本质上,useRef 就是一个其 .current 属性保存着一个可变值“盒子”,类似于 this,dom、对象等任何可变值
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值