React Hooks 学习(喂饭局3) - useRef (不会触发重渲染)

1,979 阅读2分钟

简介

useRef 总共有三种用法:

1. 作用于Dom元素
2. 获取子组件的实例(只有类组件可用)
3. 在函数组件中的一个全局变量,不会因为重复 render 重复申明, 类似于类组件的 this.xxx

什么是useRef

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

特性

  1. useRef返回一个可变的 ref 对象,该对象只有个 current 属性,初始值为传入的参数( initialValue )。
  2. 返回的 ref 对象在组件的整个生命周期内保持不变,每次返回同一个引用
  3. 当更新 current 值时并不会引起页面重新渲染
  4. 更新 useRefside effect (副作用),所以一般写在 useEffect 或 event
  5. useRef 类似于类组件的 this

使用方式/语法

const refContainer = useRef(initialValue);

举一个栗子

Parent.js

function TextInputWithFocusButton() {
    const inputEl = useRef(null);
    const onButtonClick = () => {
// `current` 指向已挂载到 DOM 上的文本输入元素\
    inputEl.current.focus();
};
return (
<View>
    <Input ref={inputEl} type="text" />
    <Button onClick={onButtonClick}>Focus thenput</Button>
</View>
);
}

本质上,useRef 就像是可以在其 .current 属性中保存一个可变值的“盒子”。 你应该熟悉 ref 这一种[访问 DOM] 的主要方式。如果你将 ref 对象以 <View ref={myRef} /> Taro 都会将 ref 对象的 .current 属性设置为相应的 DOM 节点。

然而,useRef() 比 ref 属性更有用。它可以[很方便地保存任何可变值],其类似于在 class 中使用实例字段的方式。

这是因为它创建的是一个普通 JavaScript 对象。而 useRef() 和自建一个 {current: ...} 对象的唯一区别是,useRef 会在每次渲染时返回同一个 ref 对象。

注意

当 ref 对象内容发生变化时,useRef 并不会通知你。变更 .current 属性不会引发组件重新渲染。如果想要在 Taro 绑定或解绑 DOM 节点的 ref 时运行某些代码,则需要使用[回调 ref]来实现。

再举第二个栗子

获取子组件的实例(只有类组件可用)

class Children extends PureComponent{
    render() {
        const {count} = this.props
        return (
            <div>{count}</div>
        )
    }
}
function App() {
    const [count,setCount] = React.useState(0)
    const childrenRef = React.useRef(null)
    const clickMeHandle = React.useMemo(()=>setCount((count)=> count + 1),[])
    return (
        点击了-{count}-次
        <Children ref={childrenRef} count={count}/>
        <button onClick={clickMeHandle}>点击</button>
    )
}

再举第三个栗子

在函数组件中的一个全局变量,不会因为重复 render 重复申明, 类似于类组件的 this.xxx 获取子组件的实例(只有类组件可用)

function Preson() {
    const timer = React.useRef(null)
    const clickHandle = () => {
        timer.current = setTimeout(()=>{
            console.log(timer)
        },1000)
    }
    const clearHandle = () => clearTimeout(timer.current)
    return (
        <>
            <button onClick={clickHandle}>开始</button>
            <button onClick={clearHandle}>清楚</button>
        </>
    )
}