Maison > Questions et réponses > le corps du texte
J'ai développé SPA en utilisant React 18 et L'API Movie Database (TMDB).
J'ajoute maintenant des transitions entre itinéraires(pages) avec l'aide de Framer Motion.
Pour ce faire, j'ai créé un fichier /src
中添加了一个 transition.js
avec le contenu suivant :
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;
J'utilise import transition from '../../transition'
将上述 transition
pour importer dans les composants de l'application et y envelopper les composants exportés. Voir le composant Movielist à titre d'exemple :
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);
Dans App.js j'ai la route "normale":
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;
Il y a un bac à sable, le code est ici.
Remplacer export default myComponent
更改为 export default transition(myComponent)
rendra le composant impossible à rendre.
Fais ça...
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 } }} /> </> ); };
lance cette erreur :
La demande a échoué, code d'état 404 AxiosError : la demande a échoué Code d'état 404 Une fois résolu (http://localhost:3000/static/js/bundle.js:63343:12) Dans XMLHttpRequest.onloadend (http://localhost:3000/static/js/bundle.js:62034:66)
Tout fonctionnait bien jusqu'à ce que j'essaye d'ajouter une transition de page fluide .
P粉4329300812024-03-29 16:08:40
L'erreur se produit à cause du contraire de transition
函数返回的函数没有渲染组件;它返回 undefined
.
const transition = (OgComponent) => { // the function below does not return the component return () => { <> <OgComponent /> ... </> } }
Pour résoudre ce problème, vous pouvez supprimer les accolades ou définir un retour explicite pour la fonction interne :
Retour explicite
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
Je pense que ce que vous voulez (on dirait que c'est ce que vous voulez faire, bon travail !) c'est créer un 高阶组件
将您的页面组件包装在 <来自 framermotion
的 code>motion.div pour qu'il puisse transformer votre composant pour vous.
Essayez de changer votre 转换
code par :
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; };
Vous pouvez ensuite l'appeler en passant le composant page comme TransitioningComponent
参数传递给 withTransition
et en l'exportant à partir d'un fichier jsx.
// Movielist.jsx line 41 export default withTransition(Movielist);
Voir le bac à sable du code fonctionnel ici
Voici un gif en actionCela est dû à l'expiration de la clé API stockée dans le fichier
que vous continuez à recevoir d'axios. Je pense que la requête a échoué en raison d'une réponse 403 - Accès refusé. Je n'ai pas vérifié, mais c'est ce qui me semble le plus logique. J'ai commenté certains des appels axios afin que vous puissiez voir la transformation fonctionner. 404
错误是由于codesandbox .env