Skip to content

ref

  • 记忆功能(与 useState 区别)

  • 获取 dom

  • 组件 ref

  • 暴露出组件方法

警告

  • useRef 不触发渲染

  • useRef 必须得用 current 来获取值

记忆功能

  • 不触发渲染

举例子

  • 这种情况下 它清除不了最开始的 timer,而是自己又新开了一个
js
import React, { useRef } from "react";
import Son from "./Son";
function App() {
  let timer = null;
  const handleClick = () => {
    clearInterval(timer);
    timer = setInterval(() => {
      console.log("hello");
    }, 1000);
  };
  return (
    <div>
      <h1 onClick={handleClick}>定时器</h1>
      <Son></Son>
    </div>
  );
}

export default App;

解决这个问题

  • 使用 useRef 来解决
js
import React, { useRef } from "react";
import Son from "./Son";
function App() {
  let timer = useRef(null);
  const handleClick = () => {
    clearInterval(timer.current);
    timer.current = setInterval(() => {
      console.log("hello");
    }, 1000);
  };
  return (
    <div>
      <h1 onClick={handleClick}>定时器</h1>
      <Son></Son>
    </div>
  );
}

export default App;

获取 dom

  • 获取 dom 改变文字颜色
js
import React, { useRef } from "react";
import Son from "./Son";
function App() {
  const h1dom = useRef(null);
  const handleClick = () => {
    h1dom.current.style.color = "red";
  };
  return (
    <div>
      <h1 onClick={handleClick} ref={h1dom}>
        定时器
      </h1>
      <Son></Son>
    </div>
  );
}

export default App;

组件 ref

  • 给组件绑定 ref

  • forwardRef 包裹组件

  • 通过 ref 指定元素

父元素

js
import React, { useRef } from "react";
import Son from "./Son";
function App() {
  const h1dom = useRef(null);
  const handleClick = () => {
    console.log(h1dom.current); // 就能获取到 <h1>son</h1
  };
  return (
    <div>
      <h1 onClick={handleClick}>获取dom</h1>
      <Son ref={h1dom}></Son>
    </div>
  );
}

export default App;

子元素

    1. Son 括号里面不用{} 直接就是 props,ref
    1. forwardRef 包裹组件
    1. 通过 ref 指定元素
js
import React, { forwardRef } from "react";
function Son(props, ref) {
  console.log("子元素渲染");
  return (
    <div>
      <h1 ref={ref}> Son</h1>
    </div>
  );
}

export default forwardRef(Son);

暴露出组件的方法

  • Son 还是得括号里写 props,ref

  • useImperativeHandle 指定 ref 暴露的方法或者属性,必须 return

通过 ref 暴露出我想指定的方法

子元素

js
import React, { forwardRef, useImperativeHandle } from "react";
function Son(props, ref) {
  // 指定暴露的方法
  useImperativeHandle(ref, () => {
    return {
      fn1() {
        console.log("子组件暴露的方法1");
      },
      fn2() {
        console.log("子组件暴露的方法2");
      },
    };
  });
  return (
    <div>
      <h1> Son</h1>
    </div>
  );
}

export default forwardRef(Son);

父元素

js
import React, { useRef } from "react";
import Son from "./Son";
function App() {
  const h1dom = useRef(null);
  const handleClick = () => {
    console.log(h1dom.current);
    h1dom.current.fn1();
    h1dom.current.fn2();
  };
  return (
    <div>
      <h1 onClick={handleClick}>获取dom</h1>
      <Son ref={h1dom}></Son>
    </div>
  );
}

export default App;