搜尋

首頁  >  問答  >  主體

是什麼導致在這個 React 18 應用程式中使用 transition(myComponent) 失敗?

我一直在使用 React 18電影資料庫 (TMDB) API 開發 SPA。

我現在正在Framer Motion的幫助下添加路線之間的轉換(頁面)。

為此,我在 /src 中添加了一個 transition.js 文件,其中包含以下內容:

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;

我使用 import transition from '../../transition' 將上述 transition 匯入到應用程式的元件中,並將匯出的元件包裝在其中。請參閱 Movielist 元件作為範例:

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);

在 App.js 中,我有「正常」路由:

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;

沙盒

有一個沙箱,程式碼為這裡

問題

export default myComponent 改為 export default transition(myComponent) 會使元件無法渲染

編輯

這樣做...

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 } }}
      />
    </>
  );
};

拋出此錯誤

請求失敗,狀態代碼 404 AxiosError:請求失敗 狀態碼404 解決時(http://localhost:3000/static/js/bundle.js:63343:12) 在 XMLHttpRequest.onloadend (http://localhost:3000/static/js/bundle.js:62034:66)

在嘗試新增平滑的頁面過渡之前,一切都工作正常

問題

  1. 我做錯了什麼?
  2. 解決此問題最可靠的方法是什麼?

P粉717595985P粉717595985242 天前363

全部回覆(2)我來回復

  • P粉432930081

    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 />
          </>
        )
    
      }
    }
    

    回覆
    0
  • P粉764003519

    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 調用,以便您可以看到轉換的工作情況。

    希望這個答案對您有幫助!

    回覆
    0
  • 取消回覆