什么是React的Ref?怎么用?

在React的数据流世界里,ref是一个有点特别的逃生口。它让你能直接访问DOM元素或者React组件实例,跳过props和state的那套更新机制。简单说,ref就是你通向真实DOM或组件实例的一根“直达线”。

为什么要用ref?直接操作DOM的时候

大部分时候,你应该让React通过状态来管理DOM。但有些情况你非得自己来:

  • 管理焦点、文本选中,或者媒体播放。
  • 触发命令式动画。
  • 集成需要直接操作DOM的第三方库(比如一个老旧的jQuery插件)。
    在这些场景下,你就需要ref来拿到那个真实的DOM节点。

用useRef创建和管理

在函数组件里,我们用useRef这个Hook来创建ref

import { useRef } from 'react';
function MyComponent() {
  const myInputRef = useRef(null);
  const handleClick = () => {
    myInputRef.current.focus(); // 直接调用DOM API
  };
  return (
    <>
      <input ref={myInputRef} type="text" />
      <button onClick={handleClick}>聚焦输入框</button>
    </>
  );
}

useRef返回一个可变的ref对象,它的.current属性被初始化为你传入的参数(null)。当你把myInputRef传给JSX的ref属性时,React会自动把DOM节点赋值给myInputRef.current

不仅仅是DOM:存任何可变值

ref的另一个妙用是当作一个“盒子”,用来存放那些你希望在组件生命周期内持久存在,但又不想触发重新渲染的值。

function Timer() {
  const intervalRef = useRef();
  useEffect(() => {
    intervalRef.current = setInterval(() => {
      // 做些事情
    }, 1000);
    return () => clearInterval(intervalRef.current);
  }, []);
}

这里我们把定时器ID存在intervalRef.current里。即使组件重新渲染,这个值也会保持不变,而且改变它不会导致组件重新渲染。这非常适合存储前一个状态、计时器ID或者其他实例变量。

回调ref:更精细的控制

偶尔你需要更灵活地控制ref的赋值。这时可以用“回调ref”,传一个函数给ref属性。

<input ref={(node) => { if (node) node.focus(); }} />

这个函数会在组件挂载时接收到DOM元素(node),在卸载时接收到null。你可以在函数里做任何事。

用ref要小心。它破坏了React声明式的模型,算是命令式的编程。所以,能靠stateprops解决的问题,就别用ref。把它留给那些真正需要直接接触DOM或实例的“脏活”。

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容