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

React中如何正确传递Map结构的多个refs到子组件?

React中多Map结构Ref的正确传递方式

原组件代码

以下是拆分前的Articles组件:

const Articles = ({articles}) => {

// articlesRefs - Map articles names to articles refs
// articleToLiRefs - Map articles refs to li refs
const [articlesRefs, articleToLiRefs] = useArticleLiRefs(articles);

// Code (...)

return (
<div>
    <nav><ul>
            { articles.map((article) => {
                
                const articleName = article.get('name');
                const articleRef = articlesRefs.get(articleName);
                const liRef = articleToLiRefs.get(articleRef);

                return (
                    <li
                        ref={liRef}
                        key={articleName}
                        onClick={()=> articleRef.current.scrollIntoView()}>
                        {articleName}
                    </li>
                );
            })}
        </ul></nav>
        {/* Code (...) */}
</div>
)}

两种拆分方案分析

方案一:通过props传递Ref Map

直接将存储ref的Map对象通过props传给ArticlesNav组件:

const Articles = ({articles}) => {
...
return (
...
<ArticlesNav articles={articles} articlesRefs={articlesRefs} articleToLiRefs={articleToLiRefs}  />

ArticlesNav组件内部复用原nav标签内的代码。

结论:该方案完全正确
虽然常说不建议直接传递ref,但这里传递的是存储ref的Map容器,而非单个React ref对象本身(Map是普通JavaScript对象),React不会对这类props做特殊处理,因此完全符合props的使用场景。该方案简单直观,维护成本低,是优先选择的方案。

方案二:用forwardRef传递包含多个Ref的useRef对象

父组件中用useRef包装Ref Map,再通过forwardRef传递:

const Articles = ({articles}) => {
...
const refsToForward = useRef([articlesRefs, articleToLiRefs]);
...
return (
...
<ArticlesNav articles={articles} ref={refsToForward} />

子组件内部获取:

const ArticlesNav = forwardRef( ({articles}, ref ) => {

const [articlesRefs, articleToLiRefs] = ref.current;

结论:该方案存在问题,不推荐

  1. useRef的current值不会随渲染自动更新:当articles变化导致useArticleLiRefs返回新的Map时,refsToForward.current会保留旧值,导致ArticlesNav使用过期的Ref Map,功能异常。
  2. 滥用forwardRef:forwardRef的设计初衷是让父组件直接访问子组件的DOM节点或内部实例,而非传递数据型的Ref集合,属于场景误用。

如果非要用这种方式(不推荐),需要手动更新ref的current值:

const [articlesRefs, articleToLiRefs] = useArticleLiRefs(articles);
const refsToForward = useRef([articlesRefs, articleToLiRefs]);

useEffect(() => {
  refsToForward.current = [articlesRefs, articleToLiRefs];
}, [articlesRefs, articleToLiRefs]);

总结

优先选择方案一,通过props传递存储ref的Map对象,这是最简单、可靠的实现方式。方案二属于不必要的复杂实现,且存在潜在的更新不同步问题,不建议使用。

内容的提问来源于stack exchange,提问作者Przemek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 12:16:06