React@16.x(29)useRef

目前来说,因为函数组件每次触发更新时,都会重新运行。无法像类组件一样让一些内容保持不变。
所以才出现了各种 HOOK 函数:useStateuseCallbackuseMemo 等来辅助实现和类组件相似的功能。

useRef 也是这样的目的。

1,介绍

之前的文章中介绍了 ref,用于获取组件或真实DOM元素的引用。

useRef 作用相同,不过可以在函数组件中使用。同时它会返回对象的固定引用。

换句话说,当函数组件重新运行时,useRef() 前后2次返回的对象引用地址相同。
一个节点(React元素)对应一个唯一的对象。

React.createRef() 使用举例:

import React, { useState } from "react";

export default function App() {
    const refInput = React.createRef();
    return (
        <>
            <input ref={refInput}></input>
            <button
                onClick={() => {
                    console.log(refInput.current.value);
                }}
            >
                获取 inputRef
            </button>
        </>
    );
}

换成 useRef仅需要替换一行代码:

const refInput = React.createRef();
// 替换为
const refInput = useRef();

2,和 React.createRef() 的区别

上面的代码中,看起来只是一行代码的区别,但本质上处理逻辑不同。

  • React.createRef(),如果 ref 的值发生变动(函数组件重新渲染),则将旧值设为 null
  • useRef(),函数组件重新渲染多次时,所有返回的对象的引用地址相同。

验证下:
简单修改下,将每次更新后的新 ref 放到 window 对象中对比下:

import React, { useRef, useState } from "react";

window.arr = [];
export default function App() {
    const refInput = React.createRef();
    window.arr.push(refInput);
    const [n, setN] = useState(); // 只是为了重新渲染组件。
    return (
        <>
            <input
                ref={refInput}
                type="text"
                value={n}
                onChange={(e) => {
                    setN(e.target.value);
                }}
            />
        </>
    );
}

多次改变 input.value 时,检查 window.arr

在这里插入图片描述

替换为 const refInput = useRef();

在这里插入图片描述

3,计时器的问题

在之前介绍 useEffect 时,提到了下面的写法是有问题的。

因为 useEffect 只会执行一次,所以在计时器中通过闭包获取的状态变量 n 永远都是10,

export default function App() {
    const [n, setN] = useState(10);
    useEffect(() => {
        const timer = setInterval(() => {
            setN(n - 1);
        }, 1000);
        return () => {
            clearInterval(timer);
        };
    }, []);
    return <div>{n}</div>;
}

该问题,通过将依赖项 n 传入即可。但会引起另一个问题:
每次函数重新运行,都会再次执行 useEffect,开启计时器又销毁计时器,开销很大。

export default function App() {
    const [n, setN] = useState(10);
    useEffect(() => {
        const timer = setInterval(() => {
            setN(n - 1);
        }, 1000);
        return () => {
            clearInterval(timer);
        };
    }, [n]);
    return <div>{n}</div>;
}

所以,可通过 useRef 来将函数重新运行后的新值传递给计时器,同时 useEffect 也只会运行一次,开启一次计时器!

注意,useRef() 返回的虽然是同一个对象,但 setN 修改的是它的 current 属性。所以计时器每次获取的都是新值。

export default function App() {
    const [n, setN] = useState(10);
    const refN = useRef(n);
    useEffect(() => {
        const timer = setInterval(() => {
            setN(--refN.current);
        }, 1000);
        return () => {
            clearInterval(timer);
        };
    }, []);
    return <div>{n}</div>;
}

以上。

相关推荐

  1. React@16.x23)useEffect

    2024-06-16 08:58:02       43 阅读
  2. React@16.x26)useContext

    2024-06-16 08:58:02       37 阅读
  3. React@16.x27)useCallBack

    2024-06-16 08:58:02       34 阅读
  4. React@16.x28)useMemo

    2024-06-16 08:58:02       30 阅读
  5. React@16.x25)useReducer

    2024-06-16 08:58:02       35 阅读
  6. React@16.x24)自定义HOOK

    2024-06-16 08:58:02       34 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-16 08:58:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-16 08:58:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-06-16 08:58:02       82 阅读
  4. Python语言-面向对象

    2024-06-16 08:58:02       91 阅读

热门阅读

  1. Flink 容错

    2024-06-16 08:58:02       37 阅读
  2. LeetCode 189.轮转数组

    2024-06-16 08:58:02       39 阅读
  3. 中电金信:The Financial-Grade Digital Infrastructure

    2024-06-16 08:58:02       31 阅读
  4. 小程序的生命周期

    2024-06-16 08:58:02       30 阅读
  5. 如何使用python matplotlib绘制正态分布的直方图?

    2024-06-16 08:58:02       36 阅读
  6. C++ Primer Plus v6 Chapter13 exercise 4

    2024-06-16 08:58:02       34 阅读
  7. 200. 岛屿数量

    2024-06-16 08:58:02       33 阅读
  8. 如何开发高效服务(C++ )

    2024-06-16 08:58:02       28 阅读
  9. 【@Bean和@component的区别】

    2024-06-16 08:58:02       30 阅读
  10. PHP入门教程2:控制结构和函数

    2024-06-16 08:58:02       31 阅读
  11. 印象笔记使用技巧

    2024-06-16 08:58:02       26 阅读
  12. Android开启HTTP服务

    2024-06-16 08:58:02       30 阅读
  13. FFmpeg YUV编码为H264

    2024-06-16 08:58:02       30 阅读
  14. Android BMI程序设计

    2024-06-16 08:58:02       34 阅读