React-spring:非过渡父元素下过渡组件重复渲染问题
解决react-spring移除元素时重复渲染的问题
问题核心在于useTransition对数组元素的key识别逻辑:当你把数组元素从非null改回null时,react-spring无法区分「同一位置的元素被移除」和「新元素被添加」,错误触发了重复渲染。
核心解决方案:给每个数组项绑定稳定的唯一key
固定数组每个位置的唯一标识,让react-spring能准确跟踪每个元素的进入/离开状态,而非依赖元素内容(null/非null)判断。
修改后的完整代码
HTML
<div id="app"></div>
CSS
.tiles { display: flex; gap: 10px; list-style: none; margin: 10px; padding: 0 } .tile { height: 100px; width: 100px; border: 1px solid black; border-radius: 10px; } .card { height: 100%; width: 100%; background: red; border-radius: 10px; }
JavaScript
const { useState } = React; const { createRoot } = ReactDOM; const { animated, useTransition } = ReactSpring; const App = () => { return ( <div> <Grid /> </div> ); }; const Grid = () => { // 初始化数组为带固定唯一id的对象,每个位置的id不随内容变化 const [items, setItems] = React.useState([ { id: 1, content: null }, { id: 2, content: null }, { id: 3, content: null } ]); const transition = useTransition(items, { from: { opacity: 0, transform: "translateY(-50px)" }, enter: { opacity: 1, transform: "translateY(0px)" }, leave: { opacity: 0, transform: "translateY(-50px)" }, // 指定用元素id作为跟踪key,确保稳定性 keys: item => item.id }); const add = () => { setItems(prev => prev.map(item => item.id === 1 ? { ...item, content: "Card 1" } : item )); }; const remove = () => { setItems(prev => prev.map(item => item.id === 1 ? { ...item, content: null } : item )); }; return ( <div> <button onClick={ add }>Add card to first slot</button> <button onClick={ remove }>Remove card in first slot</button> <ul className="tiles"> { transition((style, item) => ( <li className="tile" key={item.id}> { item.content && ( <animated.div className="card" style={ style }>{ item.content }</animated.div> ) } </li> )) } </ul> </div> ); }; const container = document.getElementById('app'); const root = createRoot(container); root.render(<App />);
关键修改说明
- 数组结构调整:将每个元素改为包含
id(固定唯一标识)和content(可null的实际内容)的对象,确保每个位置的跟踪标识稳定。 - useTransition配置:添加
keys: item => item.id,明确告诉react-spring用id跟踪元素,而非默认的元素内容。 - 状态更新逻辑:用
map更新指定id的元素内容,不改变数组结构和其他元素的id,保证状态变更的可预测性。
修改后,当元素被改回null时,react-spring会正确识别为同一元素的离场动画,不会触发重复渲染,动画结束后再完成元素卸载。
内容的提问来源于stack exchange,提问作者Andries
相关产品推荐
相关产品推荐

