You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中如何正确传递DOM元素引用给平滑滚动组件?

React 平滑滚动组件的DOM引用传递优化方案

问题场景

我实现了一个平滑滚动的工具组件:

const SmoothScroller = ({
    text,
    target,
}: {
    text: string
    target: HTMLElement | null
}) => {
    const scrollToTarget = () => {
        target?.scrollIntoView({
            behavior: 'smooth',
        })
    }

    return <a onClick={scrollToTarget}>{text}</a>
}

使用时需要创建DOM元素引用并传入:

const ref = useRef<HTMLParagraphElement>(null)

return <>
<SmoothScroller
    target={ref.current}
    text="Scroll to paragraph"
/>
<p ref={ref} className="read-the-docs">
    Click on the Vite and React logos to learn more
</p>
</>

但这种方式无法正常工作,因为渲染时ref.current可能为null,且后续ref.current更新后不会触发组件重新传参。虽然可以改成传递获取元素的函数(target: () => HTMLElement | null),但存在更优方案。

最优解决方案:传递React Ref对象而非ref.current

直接将整个Ref对象传递给组件,而不是它的current属性。Ref对象在组件生命周期内是稳定的,不会随重渲染变化,且点击时可以获取最新的DOM元素引用。

修改后的组件代码

import React from 'react'

const SmoothScroller = ({
    text,
    targetRef,
}: {
    text: string
    targetRef: React.RefObject<HTMLElement>
}) => {
    const scrollToTarget = () => {
        // 点击时才获取最新的current值
        targetRef.current?.scrollIntoView({
            behavior: 'smooth',
        })
    }

    return <a onClick={scrollToTarget}>{text}</a>
}

使用方式

const ref = useRef<HTMLParagraphElement>(null)

return <>
<SmoothScroller
    targetRef={ref}  // 直接传递ref对象
    text="Scroll to paragraph"
/>
<p ref={ref} className="read-the-docs">
    Click on the Vite and React logos to learn more
</p>
</>

方案优势

  1. 避免初始null问题:点击时才访问targetRef.current,此时DOM元素已经挂载完成,能确保获取到有效的元素引用(只要目标元素存在)。
  2. 稳定性更高:Ref对象本身不会在重渲染时创建新实例,不会触发SmoothScroller组件的不必要重渲染。
  3. 符合React最佳实践:直接传递Ref对象是React中跨组件传递DOM引用的标准方式,代码更直观易懂。

内容的提问来源于stack exchange,提问作者Michał Turczyn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 01:05:13