Was führt dazu, dass der Übergang (myComponent) in dieser React 18-Anwendung fehlschlägt?
P粉717595985
P粉717595985 2024-03-28 19:34:04
0
2
387

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;

Sandbox

Es gibt eine Sandbox, der Code ist hier.

Frage

Durch

Ersetzen export default myComponent 更改为 export default transition(myComponent) wird die Komponente unrenderbar gemacht.

Bearbeiten

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 .

Frage

  1. Was habe ich falsch gemacht?
  2. Was ist der zuverlässigste Weg, dieses Problem zu lösen?

P粉717595985
P粉717595985

Antworte allen(2)
P粉432930081

发生错误是因为从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粉764003519

我认为您想要的(看起来这就是您想要做的,干得好!)是创建一个 高阶组件 将您的页面组件包装在 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 调用,以便您可以看到转换的工作情况。

希望这个答案对您有所帮助!

Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage