如何通过ID从React Spring的useSprings数组中移除元素?
使用React Spring useSprings钩子时移除特定动画元素的问题
我正在用React Spring的useSprings钩子实现动画,用activeTokens数组的长度控制弹簧数量,添加token和渲染动画都正常,但移除特定token时遇到了麻烦——没法把token的id和对应的spring元素关联起来,导致点击后无法正确移除目标元素。
我的钩子实现:
const [activeTokens, setActiveTokens] = useState([]); const [tokenSprings, setTokenSprings] = useSprings(activeTokens.length, (index) => { return { from: { transform: `translate3d(0px, 0px, 0)`}, to: async (next) => { var rotate = randomInt(800, 7200); await next({ transform: `translate3d(1px, 1px, 0)`, config: { mass: 0.4, tension: 5, friction: 3 }, }) }, } } );
JSX渲染代码:
tokenSprings.map((spring, index) => ( <animated.div className="text-white text-2xl absolute cursor-pointer" key={index} style={spring}> <div onClick={() => handleTokenClick(index)}> <FontAwesomeIcon icon={faMoneyBill}></FontAwesomeIcon> </div> </animated.div > ))
点击处理函数:
function handleTokenClick(tokenId) { setActiveTokens(activeTokens => activeTokens.filter(token => token.id !== tokenId)); }
显然这行不通,因为tokenSprings里没有token的id信息,没法用index去匹配token.id。查了React Spring文档也没找到给spring元素加标识的方法,想问问有没有办法给每个spring绑定id?如果不行,那正确移除特定spring元素的做法是什么?
解决方案
核心问题是你现在只用数组长度创建springs,没有把token和对应的spring绑定起来。正确的做法是直接基于activeTokens数组的元素生成springs,这样每个spring就能和具体的token关联:
- 修改useSprings的用法
不需要单独维护tokenSprings的状态(useSprings本身会返回更新后的spring配置),直接传入activeTokens.length,同时在配置函数里拿到对应位置的token:
const [activeTokens, setActiveTokens] = useState([]); // 直接生成对应数量的spring配置,无需额外维护状态 const tokenSprings = useSprings(activeTokens.length, (index) => { // 拿到当前index对应的token const token = activeTokens[index]; return { from: { transform: `translate3d(0px, 0px, 0)`}, to: async (next) => { const rotate = randomInt(800, 7200); await next({ transform: `translate3d(1px, 1px, 0)`, config: { mass: 0.4, tension: 5, friction: 3 }, }) }, } });
- 修改JSX渲染逻辑
不要遍历tokenSprings,而是遍历activeTokens,通过index对应到spring配置,同时传递token.id而非index:
{activeTokens.map((token, index) => { const spring = tokenSprings[index]; return ( <animated.div className="text-white text-2xl absolute cursor-pointer" key={token.id} // 用token.id作为key,避免index带来的渲染问题 style={spring} > <div onClick={() => handleTokenClick(token.id)}> <FontAwesomeIcon icon={faMoneyBill} /> </div> </animated.div> ); })}
- 点击处理函数保持不变
现在传递的是正确的token.id,过滤逻辑可以正常生效:
function handleTokenClick(tokenId) { setActiveTokens(prevTokens => prevTokens.filter(token => token.id !== tokenId)); }
补充说明
- 用
token.id作为React元素的key,避免使用index作为key导致的组件复用错误,尤其是在数组元素增删时。 - 通过遍历
activeTokens数组,你可以直接获取每个token的标识,同时对应到相同index的spring配置,完美建立起token和动画元素的关联。
内容的提问来源于stack exchange,提问作者jamesdlivesinatree
相关产品推荐
相关产品推荐

