React Spring useTransition 入场离场动画冲突与重复渲染问题
React Spring 动态路由动画问题排查与修正
问题1:首次加载底部链接区域重复渲染两次
问题根因有两点:
- 开发环境开启React StrictMode 严格模式时,组件首次挂载阶段会执行双重渲染校验,如果把动画配置、transition实例生成逻辑直接写在组件函数体顶层、未做引用缓存,会在两次渲染中生成全新的动画实例,连带触发链接区域两次重渲染。
useTransition未正确绑定路由key依赖:初始化路由匹配时,会先以空location值触发一次初始渲染,待router完成首次路由匹配后再触发第二次正式渲染,两次渲染均命中链接区域渲染分支就会出现重复渲染现象。如果底部链接子组件未做React.memo缓存,React Spring逐帧更新动画样式带来的父组件重渲染,还会进一步放大重复渲染的问题。
问题2:路由切换时新旧链接堆叠、动画时序错乱
问题根因有三点:
useTransition缺失关键时序配置:默认配置下路由key变更时,新节点入场动画和旧节点离场动画是并行执行的,DOM中会同时存在新旧两个链接组节点,自然出现堆叠。需要添加exitBeforeEnter: true配置,强制旧节点离场动画完全结束、节点卸载后,再触发新节点的入场动画,从流程上避免两个节点同时存在。- 过渡容器定位配置错误:执行过渡动画的链接组容器必须设置
position: absolute,同时父级容器设置position: relative预留展示位,否则新旧节点作为文档流内的块级元素,就算时序正确也会出现布局跳动、短暂堆叠的问题。 - 动画状态值设置不完整:如果leave离场状态的透明度终值未设为0,旧节点在离场动画全程都会保持可见,和新节点的淡入效果叠加就会出现内容重叠的错乱表现。
核心修正代码参考
import { useTransition, animated } from '@react-spring/web' import { useLocation } from 'react-router-dom' import { memo } from 'react' import LinksGroup from './LinksGroup' // 固定动画配置抽离到组件外,避免每次渲染生成新引用 const SPRING_CONFIG = { from: { opacity: 0, transform: 'translateY(12px)' }, enter: { opacity: 1, transform: 'translateY(0)' }, leave: { opacity: 0, transform: 'translateY(-8px)' }, config: { tension: 280, friction: 24 }, exitBeforeEnter: true, // 强制离场完成后再触发入场 } const DynamicScreen = memo(() => { const location = useLocation() const transitions = useTransition(location, { ...SPRING_CONFIG, keys: (loc) => loc.pathname, // 明确绑定路由path作为动画key }) return ( <div className="dynamic-screen" style={{ position: 'relative', minHeight: '100vh' }}> {/* 页面主内容区域 */} <div className="links-wrapper" style={{ position: 'absolute', bottom: 48, left: 0, width: '100%' }} > {transitions((style, currentLoc) => ( <animated.div style={style}> <LinksGroup currentPath={currentLoc.pathname} /> </animated.div> ))} </div> </div> ) }) export default DynamicScreen
内容的提问来源于stack exchange,提问作者goldylucks
相关产品推荐
相关产品推荐

