第33节——useRef

一、概念

useRef,他的作用是“勾住”某些组件挂载完成或重新渲染完成后才拥有的某些对象,并返回该对象的引用。该引用在组件整个生命周期中都固定不变,该引用并不会随着组件重新渲染而失效。返回一个可变的 ref 对象,该对象只有个 current 属性,初始值为传入的参数( initialValue )。返回的 ref 对象在组件的整个生命周期内保持不变。当更新 current 值时并不会 re-render ,这是与 useState 不同的地方。更新 useRef 是 side effect (副作用),所以一般写在 useEffect 或 event handler 里。useRef 类似于类组件的 this

const refContainer = useRef(initialValue);

二、useRef是来解决什么问题的

1、JSX组件转换后对应的真实DOM对象。如何获取input的真实dom

useRef只适合“勾住”小写开头的类似原生标签的组件。如果是自定义的react组件(自定义的组件必须大写字母开头),那么是无法使用useRef(当然也有一些奇淫技巧后面我们后续课程会讲)的。比如,我们如何获取这个 真实DOM呢。那么就可以使用useRef

初始化input聚焦
import React,{useEffect,useRef} from 'react'


function Component() {
  //先定义一个inputRef引用变量,用于“勾住”挂载网页后的输入框
  const inputRef = useRef(null);


  useEffect(() => {
    //inputRef.current就是挂载到网页后的那个输入框,一个真实DOM,因此可以调用html中的方法focus()
    inputRef.current.focus();
  },[]);


  return 
{/* 通过 ref 属性将 inputRef与该输入框进行“挂钩” */}
} export default Component

2、在useEffect中创建的变量,如何在useEffect 以外的地方,获取并引用

例子

1、组件中有一个变量count,当该组件挂载到网页后,count每秒自动 +1。

2、组件中有一个按钮,点击按钮可以停止count自动+1

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


function Component() {
  const [count,setCount] =  useState(0);
  const timerRef = useRef(null);//先定义一个timerRef引用变量,用于“勾住”useEffect中通过setIntervale创建的计时器


  useEffect(() => {
    //将timerRef.current与setIntervale创建的计时器进行“挂钩”
    timerRef.current = setInterval(() => {
      setCount((prevData) => { return prevData +1});
    }, 1000);
    return () => {
      //通过timerRef.current,清除掉计时器
      clearInterval(timerRef.current);
    }
  },[]);


  const clickHandler = () => {
    //通过timerRef.current,清除掉计时器
    clearInterval(timerRef.current);
  };


  return (
    
{count}
) } export default Component

4、父组件调用子组件内的方法

注意:除非情况非常特殊,否则一般情况下都不要采用 父组件调用子组件的函数 这种策略

实现思路

父组件中通过 useRef 定义一个钩子变量,例如 childFunRef

父组件通过参数配置,将 childFunRef 传递给子组件

子组件在自己的 useEffect() 中定义一个函数,例如 doSomting()

划重点:一定要在 useEffect() 中定义 doSomting(),不能直接在子组件内部定义。

因为如果 doSomting() 定义在子组件内部,那么就会造成每一次组件刷新都会重新生成一份 doSomthing()

然后将 doSomting() 赋值到 childFunRef.current 中

这样,当父组件想调用子组件中的 doSomting() 时,可执行 childFunRef.current.doSomting()

父组件
import { useRef } from "react";
import ChildComponent from "./child";


const ParentComponent = () => {
  const childFunRef = useRef();
  const handleOnClick = () => {
    if (childFunRef.current) {
      childFunRef.current.doSomething();
    }
  };
  return (
    
); }; export default ParentComponent;
子组件
import { useEffect, useState } from "react";


const ChildComponent = ({ funRef }) => {
  const [num, setNum] = useState(0);
  useEffect(() => {
    const doSomething = () => {
      setNum(Math.floor(Math.random() * 100));
    };
    funRef.current = { doSomething }; //在子组件中修改父组件中定义的childFunRef的值
  }, [funRef]);
  return 
{num}
; }; export default ChildComponent;

三、useRef与createRef的区别

1、useRef是针对函数组件的,如果是类组件则使用React.createRef()。

2、React.createRef()也可以在函数组件中使用。useRef只能在react hooks中使用

3、createRef每次都会返回个新的引用;而useRef不会随着组件的更新而重新创建

你可能感兴趣的:(react,react.js,javascript,前端)