Qu'est-ce qui fait échouer la transition (myComponent) dans cette application React 18 ?
P粉717595985
P粉717595985 2024-03-28 19:34:04
0
2
383

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;

Bac à sable

Il y a un bac à sable, le code est ici.

Question

Remplacer export default myComponent 更改为 export default transition(myComponent) rendra le composant impossible à rendre.

Modifier

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 .

Question

  1. Qu'est-ce que j'ai fait de mal ?
  2. Quel est le moyen le plus fiable de résoudre ce problème ?

P粉717595985
P粉717595985

répondre à tous(2)
P粉432930081

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粉764003519

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 action

Cela 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

J'espère que cette réponse vous aidera !

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal