react-transition-group配合react路由触发findDOMNode废弃警告原理求解
原理说明
1. 警告触发的根本原因
你使用的react-transition-group v4及更低版本中,CSSTransition组件默认会在过渡状态更新时调用已被废弃的findDOMNode API定位要加动画的DOM节点,React严格模式下会对这类废弃API调用抛出警告。
2. 首次传ref无效的原因
CSSTransition用来接收目标DOM引用的属性不是标准的ref,而是专门的nodeRef prop。你将useRef生成的引用直接赋值给ref属性,CSSTransition内部并不会读取该值,所以还是会走findDOMNode的逻辑,警告不会消失。
补充:标准的ref修复方案如下,后续有复杂需求可以使用:
const nodeRef = useRef(null); // 组件内写法 <CSSTransition nodeRef={nodeRef} // 传nodeRef而不是ref in={match!=null} timeout={300} classNames="page" unmountOnExit mountOnEnter > <div ref={nodeRef} className="page"> {/* 把ref绑定到内部DOM */} <Component /> </div> </CSSTransition>
3. 加key后警告消失的核心逻辑
React的key属性用来标识组件实例的唯一性,只要key值发生变化,React就会直接销毁旧的组件实例,创建全新实例重新挂载,完全不会复用之前的实例。
你把key的值和in属性的判断条件完全绑定,意味着每次in的状态切换(路由匹配状态变化)时,CSSTransition的key都会同步变化,相当于每次过渡都使用全新的CSSTransition实例。
再结合你配置的mountOnEnter和unmountOnExit属性:
- 当
in为true时,CSSTransition才会挂载,挂载时初始状态就是进入完成状态,不需要执行「状态更新时查找旧DOM」的逻辑,不会触发findDOMNode调用 - 当
in为false时,CSSTransition直接卸载,没有后续的状态更新操作,也不会触发findDOMNode
你相当于用key强制重建组件的方式,直接绕开了CSSTransition内部会调用findDOMNode的代码路径,所以警告自然消失,和你是否传了ref没有任何关系。
小提示:当前简单路由过渡场景下这种写法是可用的,如果后续涉及更复杂的嵌套动画,更推荐用上述
nodeRef的标准方案,避免强制重建组件导致动画丢失的问题。
内容的提问来源于stack exchange,提问作者Marc Abdel Wahed

