如何在Loader组件动画结束后加载React Router的GamesPage组件?
实现方案:Loader动画结束后加载GamesPage组件
这里提供两种更可靠的实现思路,优先推荐利用framer-motion的动画完成回调(比固定setTimeout更精准,避免动画时长波动导致的不同步),同时也会给出基于setTimeout的实现方式。
方案一:利用framer-motion的onComplete回调(推荐)
这种方式直接绑定动画的实际结束时机,不会因为性能波动或动画序列变化出现偏差。
1. 修改Loader组件,添加动画完成回调
// Loader.jsx import { motion } from 'framer-motion'; const Loader = ({ onAnimationFinish }) => { // 定义动画变体,包含完整的进入+退出序列 const loaderVariants = { initial: { opacity: 0, scale: 0.8 }, animate: { opacity: 1, scale: 1, transition: { duration: 1.2 } }, exit: { opacity: 0, scale: 0.8, transition: { duration: 0.8 }, // 动画退出完成时触发外部回调 onComplete: () => onAnimationFinish?.() } }; return ( <motion.div variants={loaderVariants} initial="initial" animate="animate" exit="exit" className="fixed inset-0 flex items-center justify-center bg-white" > <motion.div className="w-24 h-24 border-4 border-blue-500 border-t-transparent rounded-full" animate={{ rotate: 360 }} transition={{ repeat: Infinity, duration: 1.5, ease: "linear" }} /> </motion.div> ); }; export default Loader;
2. 路由跳转逻辑处理
如果你的首页就是Loader页面,动画完成后直接跳转到/games:
// Home.jsx(首页) import { useNavigate } from 'react-router-dom'; import Loader from './Loader'; const Home = () => { const navigate = useNavigate(); const handleLoaderFinish = () => { // 动画完全结束后跳转至游戏页面 navigate('/games'); }; return <Loader onAnimationFinish={handleLoaderFinish} />; }; export default Home;
然后在App的路由配置中直接映射:
// App.jsx import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import Home from './Home'; import GamesPage from './GamesPage'; function App() { return ( <Router> <Routes> <Route path="/" element={<Home />} /> <Route path="/games" element={<GamesPage />} /> </Routes> </Router> ); } export default App;
方案二:基于setTimeout的固定延迟实现
如果必须使用setTimeout,需要确保延迟时间大于等于Loader动画的总时长(进入+退出):
1. 自定义延迟路由组件
// DelayedRoute.jsx import { useState, useEffect } from 'react'; import { useLocation } from 'react-router-dom'; import Loader from './Loader'; const DelayedRoute = ({ element, delay = 2000 }) => { const [isLoading, setIsLoading] = useState(true); const location = useLocation(); useEffect(() => { // 路由切换时重置状态并启动定时器 setIsLoading(true); const timer = setTimeout(() => { setIsLoading(false); }, delay); // 清理定时器,避免内存泄漏 return () => clearTimeout(timer); }, [location, delay]); return isLoading ? <Loader /> : element; }; export default DelayedRoute;
2. 路由配置中使用自定义组件
// App.jsx import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import DelayedRoute from './DelayedRoute'; import GamesPage from './GamesPage'; function App() { return ( <Router> <Routes> <Route path="/" element={<DelayedRoute element={<GamesPage />} delay={2000} />} /> {/* 或者直接给/games路由加延迟 */} <Route path="/games" element={<DelayedRoute element={<GamesPage />} delay={2000} />} /> </Routes> </Router> ); } export default App;
注意事项
- 若使用
setTimeout,延迟时间要设置为Loader动画的总时长(进入动画时长+退出动画时长),否则会出现动画未结束就切换页面的情况。 - 利用
onComplete回调的方式更贴合动画实际执行情况,适合复杂动画序列场景。
内容的提问来源于stack exchange,提问作者user15979146
相关产品推荐
相关产品推荐

