Ich habe SPA mit React 18 und The Movie Database (TMDB) API entwickelt.
Ich füge jetzt Übergänge zwischen Routen (Seiten) mit Hilfe von Framer Motion hinzu.
Dazu habe ich eine /src
中添加了一个 transition.js
-Datei mit folgendem Inhalt erstellt:
import { motion } from "framer-motion"; const transition = (OgComponent) => { return () => { <> <OgComponent /> <motion.div className="slide-in" initial={{ opacity: 0, x: '-100px' }} animate={{ opacity: 1, x: 0, transition: { duration: 0.3 } }} exit={{ opacity: 0, x: 0, transition: { duration: 0.3 } }} > <motion.div /> </> } } export default transition;
Ich verwende import transition from '../../transition'
将上述 transition
, um die Komponenten der Anwendung zu importieren und die exportierten Komponenten darin einzuschließen. Sehen Sie sich die Movielist-Komponente als Beispiel an:
import { useEffect, useState } from 'react'; import { useLocation } from 'react-router-dom'; import axios from 'axios'; import Moviecard from '../Moviecard/Moviecard'; import transition from '../../transition'; function Movielist({ page_title, listMovies }) { const API_URL = 'https://api.themoviedb.org/3'; const location = useLocation(); const [movies, setMovies] = useState([]); const getMovies = async () => { const { data: { results } } = await axios.get(`${API_URL}/movie/${listMovies}`, { params: { api_key: process.env.REACT_APP_API_KEY } }); setMovies(results); } const displayMovies = () => { return movies.map(movie => ( <Moviecard key={movie.id} movie={movie} /> )) } useEffect(() => { getMovies(); }, [location]) return ( <> <h1 className="page-title">{ page_title }</h1> <div className="row movie-list"> { displayMovies() } </div> </> ); } export default transition(Movielist);
In App.js habe ich den „normalen“ Weg:
import { Routes, Route } from 'react-router-dom'; import Topbar from './components/Topbar/Topbar'; import Footer from './components/Footer/Footer'; import Movielist from './components/Movielist/Movielist'; import Moviedetails from './components/Moviedetails/Moviedetails'; import Actordetails from './components/Actordetails/Actordetails'; function App() { return ( <div className="App"> <Topbar /> <div className="container"> <Routes> <Route path="/" element={<Movielist page_title="Now playing" listMovies="now_playing" />} /> <Route path="/top-rated" element={<Movielist page_title="Top rated" listMovies="top_rated" />} /> <Route path="/movie/:id" element={<Moviedetails />} /> <Route path="/actor/:id" element={<Actordetails />} /> </Routes> </div> <Footer /> </div> ); } export default App;
Es gibt eine Sandbox, der Code ist hier.
Ersetzen export default myComponent
更改为 export default transition(myComponent)
wird die Komponente unrenderbar gemacht.
Mach das...
const transition = (OgComponent) => { return () => ( <> <OgComponent /> <motion.div className="slide-in" initial={{ opacity: 0, x: 0 }} animate={{ opacity: 1, x: 100, transition: { duration: 0.5 } }} exit={{ opacity: 0, x: 0, transition: { duration: 0.5 } }} /> </> ); };
wirft diesen Fehler aus:
Anfrage fehlgeschlagen, Statuscode 404 AxiosError: Anfrage fehlgeschlagen Statuscode 404 Wenn gelöst (http://localhost:3000/static/js/bundle.js:63343:12) In XMLHttpRequest.onloadend (http://localhost:3000/static/js/bundle.js:62034:66)
Alles hat gut funktioniert, bis ich versucht habe, einen reibungslosen Seitenübergang hinzuzufügen .
发生错误是因为从
transition
函数返回的函数没有渲染组件;它返回undefined
相反。要解决此问题,您可以删除大括号或为内部函数定义显式返回:
显式返回
我认为您想要的(看起来这就是您想要做的,干得好!)是创建一个
高阶组件
将您的页面组件包装在 framermotion 的 code>motion.div,以便它可以为您转换您的组件。尝试将您的
转换
代码更改为:然后,您可以通过将页面组件作为
TransitioningComponent
参数传递给withTransition
并从 jsx 文件中导出来调用它。在此处查看工作代码沙箱
这是它的实际操作的 gif
您不断从 axios 收到的
404
错误是由于codesandbox.env
文件中存储的 API 密钥过期所致。我认为查询失败是由于 403 - 访问被拒绝响应。我没有检查,但这对我来说最有意义。我注释掉了一些 axios 调用,以便您可以看到转换的工作情况。希望这个答案对您有所帮助!