Heim > Fragen und Antworten > Hauptteil
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 .
P粉4329300812024-03-29 16:08:40
发生错误是因为从transition
函数返回的函数没有渲染组件;它返回 undefined
相反。
const transition = (OgComponent) => { // the function below does not return the component return () => { <> <OgComponent /> ... </> } }
要解决此问题,您可以删除大括号或为内部函数定义显式返回:
显式返回
const transition = (OgComponent) => { return () => { 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 } }} /> <motion.div /> </> ) } }
P粉7640035192024-03-29 10:18:19
我认为您想要的(看起来这就是您想要做的,干得好!)是创建一个 高阶组件
将您的页面组件包装在 <来自 framermotion
的 code>motion.div,以便它可以为您转换您的组件。
尝试将您的转换
代码更改为:
import React from "react"; import { motion } from "framer-motion"; export const withTransition = (TransitioningComponent) => { class WithTransition extends React.Component { render() { return ( <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.5 } }} > <TransitioningComponent {...this.props} /> </motion.div> ); } } WithTransition.displayName = `WithTransition(${ TransitioningComponent.displayName || TransitioningComponent.name })`; return WithTransition; };
然后,您可以通过将页面组件作为 TransitioningComponent
参数传递给 withTransition
并从 jsx 文件中导出来调用它。
// Movielist.jsx line 41 export default withTransition(Movielist);
在此处查看工作代码沙箱
这是它的实际操作的 gif
您不断从 axios 收到的 404
错误是由于codesandbox .env
文件中存储的 API 密钥过期所致。我认为查询失败是由于 403 - 访问被拒绝响应。我没有检查,但这对我来说最有意义。我注释掉了一些 axios 调用,以便您可以看到转换的工作情况。
希望这个答案对您有所帮助!