【问题标题】:React Transition Group: How to pass ref to mapped component to avoid Warning: findDOMNode is deprecated in StrictModeReact Transition Group:如何将 ref 传递给映射的组件以避免警告:在 StrictMode 中不推荐使用 findDOMNode
【发布时间】:2021-06-09 17:32:19
【问题描述】:

我有以下代码来呈现带有动画安装/卸载的过滤列表:

function List({ list, templates, transition }) {
  return (
    <TransitionGroup 
        className="wscfl-list"
        component="ul"
    >
    {list.map((item) => (
      <CSSTransition
        key={item.id}
        timeout={transition.timeout}
        classNames={'wscfl-list__' + item.type + '-'}
      >
        <li className={'wscfl-list__' + item.type} >
          <Item item={item} template={templates[item.type]} pkey={item.id}/>
        </li>
      </CSSTransition>
    ))}
    </TransitionGroup>
  );
}

这将引发我想避免的Warning: findDOMNode is deprecated in StrictMode. findDOMNode was passed an instance of Transition which is inside StrictMode. Instead, add a ref directly to the element you want to reference.

我知道我应该为 CSSTransition (https://github.com/reactjs/react-transition-group/releases/tag/v4.4.0) 添加一个引用:

import React from "react"
import { CSSTransition } from "react-transition-group"

const MyComponent = () => {
  const nodeRef = React.useRef(null)
  return (
    <CSSTransition nodeRef={nodeRef} in timeout={200} classNames="fade">
      <div ref={nodeRef}>Fade</div>
    </CSSTransition>
  )
}

但是我不能在地图回调中使用 useRef,因为它不允许在回调中使用钩子。

我尝试创建一个引用数组 (How target DOM with react useRef in map):

function List({ list, templates, transition }) {
  // https://stackoverflow.com/questions/54940399/how-target-dom-with-react-useref-in-map/55105849
  const refsArray = [];
  for (var i= 0; i < list.length; i++) {
    refsArray.push(React.createRef());
  }
  let refs = React.useRef(refsArray);
  React.useEffect(() => {
    refs.current[0].current.focus()
  }, []);
  return (
    <TransitionGroup 
        className="wscfl-list"
        component="ul"
    >
    {list.map((item, i) => (
      <CSSTransition
        key={item.id}
        nodeRef={refs.current[i]}
        timeout={transition.timeout}
        classNames={'wscfl-list__' + item.type + '-'}
      >
        <li ref={refs.current[i]} className={'wscfl-list__' + item.type} >
          <Item item={item} template={templates[item.type]} pkey={item.id}/>
        </li>
      </CSSTransition>
    ))}
    </TransitionGroup>
  );
}

但这会在第一次渲染时抛出错误TypeError: Cannot read property 'current' of undefined

   9 | }
  10 | let refs = React.useRef(refsArray);
  11 | React.useEffect(() => {
> 12 |   refs.current[0].current.focus()
     | ^  13 | }, []);
  14 | return (
  15 |   <TransitionGroup 

有没有办法在不使用 findDOMNode 的情况下将 CSSTransition 用于映射组件?

【问题讨论】:

    标签: reactjs react-transition-group react-ref


    【解决方案1】:

    无需使用 ref 数组即可处理此问题的最简单方法是提取另一个组件中的映射内容

    const Content = ({item, transition, templates, ...rest}) =>  {
      const nodeRef = React.useRef(null)
      return(
        <CSSTransition
            {...rest}
            nodeRef={nodeRef}
            timeout={transition.timeout}
            classNames={'wscfl-list__' + item.type + '-'}
          >
            <li ref={nodeRef} className={'wscfl-list__' + item.type} >
              <Item item={item} template={templates[item.type]} pkey={item.id}/>
            </li>
          </CSSTransition>
    
       )
    }
    
    function List({ list, templates, transition }) {
      return (
        <TransitionGroup 
            className="wscfl-list"
            component="ul"
        >
        {list.map((item) => (
            <Content item={item} key={item.id} templates={templates} transition={transition}/>
        ))}
        </TransitionGroup>
      );
    }
    

    【讨论】:

    • 谢谢,但这会破坏动画。我想 CSSTransition 必须是 TransitionGroup 的直系后代?
    • @TeeBoek 这不是必需品。 TransitionGroup 将某些道具传递给它的孩子,您可以使用休息语法将其转发给 CSSTransition。我已经编辑了我的答案。还要检查这个相同的 Codesandbox:codesandbox.io/s/gracious-gould-iktqw?file=/index.js 我已经在其中进行了测试
    • 很高兴知道!我不得不修改您的代码并将 key={item.id} 提升到 Content 组件以避免唯一键警告。
    • @TeeBoek 是的,我在复制粘贴时错过了关键的东西。很高兴答案有所帮助
    • 谢谢你,经过一天无数次的尝试,问题终于解决了
    猜你喜欢
    • 2021-10-12
    • 2020-09-23
    • 1970-01-01
    • 2020-07-07
    • 2021-04-08
    • 2020-12-19
    • 2020-09-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多