React严格模式下react-transition-group报findDOMNode废弃,加nodeRef后UI异常
问题原因
你在组件顶层仅声明了一个共用的nodeRef引用,当通过map循环渲染多个待办项时,这个唯一的ref会在循环过程中被不断覆盖,最终只会指向最后一个渲染的<li>元素。所有<CSSTransition>组件拿到的nodeRef都指向同一个元素,导致前面的列表项找不到对应的DOM节点,无法正常渲染和触发动画,因此出现部分元素丢失的异常。
正确修复方案
推荐将循环渲染的单个待办项抽离为独立的子组件,每个子组件内部单独维护自己的nodeRef,保证每个<CSSTransition>和对应的DOM节点一一绑定,不会出现引用冲突。
步骤1:抽离独立的TodoItem子组件
const TodoItem = ({ task, toggleTodo, styles }) => { // 每个子组件内部维护独立的ref const nodeRef = React.useRef(null); return ( <CSSTransition timeout={500} classNames={styles} nodeRef={nodeRef} > <li ref={nodeRef}> <TodoTask todo={task} onClick={(todo) => toggleTodo({ data: todo })} /> </li> </CSSTransition> ) }
步骤2:父组件中引用子组件
<ul> <TransitionGroup className="todo-list"> {incompleteTodos.map((task) => ( <TodoItem key={task.id} task={task} toggleTodo={toggleTodo} styles={styles} /> ))} </TransitionGroup> </ul>
可选方案:使用ref数组(不推荐)
如果不想抽离子组件,也可以创建ref数组存储每个列表项的独立引用,但是该方案需要手动维护ref数组和列表项的对应关系,适合列表项固定、无频繁增删排序的场景:
// 父组件内声明ref数组 const nodeRefs = React.useRef([]); // 渲染时分配独立ref <ul> <TransitionGroup className="todo-list"> {incompleteTodos.map((task, index) => { if (!nodeRefs.current[index]) { nodeRefs.current[index] = React.createRef(); } return ( <CSSTransition key={task.id} timeout={500} classNames={styles} nodeRef={nodeRefs.current[index]} > <li ref={nodeRefs.current[index]}> <TodoTask todo={task} onClick={(todo) => toggleTodo({ data: todo })} /> </li> </CSSTransition> ) })} </TransitionGroup> </ul>
内容的提问来源于stack exchange,提问作者Varun Sukheja
相关产品推荐
相关产品推荐

