【问题标题】:(React) Lazy Loading components that use Framer-Motion page transitions(React) 使用 Framer-Motion 页面转换的延迟加载组件
【发布时间】:2021-05-25 05:03:00
【问题描述】:

向上、向下和横向寻找解决此问题的方法。

我的目标是将延迟加载分配给我的 React 网站中的几乎所有组件。但是,当这些组件进入和退出时,这些组件会利用成帧器运动页面转换。页面转换和延迟加载的组合导致组件在作为路由单击时不再正确加载。

我从这篇文章 (https://github.com/reactjs/react-transition-group/issues/580) 中找到了灵感,并尝试引入“react-lazy-with-preload”包 (https://github.com/ianschmitz/react-lazy-with-preload),但未能成功。

有人知道这个问题的解决方案吗?我肯定不会是唯一一个尝试对 React 网站进行数据拆分的人,该网站使用具有帧运动页面转换的组件。

App.js 代码如下:

import React, { Suspense } from 'react';
import { Switch, Route, useLocation } from 'react-router-dom';
import lazy from "react-lazy-with-preload";
import { AnimatePresence } from 'framer-motion';

////////////////////////////////////////////////
//PREPARE PAGES OF WEBSITE AS LAZY LOADED PAGES
import Navbar from './components/layout/Navbar/Navbar';
import Footer from './components/layout/Footer/Footer';
import Home from './components/layout/Homepage/Home';
const Dashboard = lazy(() => import('./components/dashboard/Dashboard'));
const Login = lazy(() => import('./components/authorization/login/LoginComponent'));
const SignUp = lazy(() => import('./components/authorization/signup/SignupComponent'));
const OurTeam  = lazy(() => import( './components/layout/OurTeam/OurTeam'));

function App () {

  let location = useLocation();

  //Trying to preload the components which contain Page-Transitions
  OurTeam.preload();
  Login.preload();
  SignUp.preload();
  Dashboard.preload();


    return (
      
        <div className='page-container'>

          <div className='content-wrap'>

            <Navbar />

            <AnimatePresence exitBeforeEnter> {/* Exit page transition occurs before next page loads. */}

            <ScrollToTop/> {/* Causes the screen to scroll to the top after routing occurs. */}

              <Switch location={location} key={location.pathname}> {/* Switch is used to make sure only 1 route is loaded up at a time. location and key are used for page transition animation.*/}
                
                {/*Homepage will not be data-split and will always be loaded */}
                <Route exact path='/' component={Home} />

                <Suspense fallback='Loading...'>
                  <Route path='/OurTeam' component={OurTeam} />
                </Suspense>
                  
                <Suspense fallback='Loading...'>
                  <Route path='/dashboard' component={Dashboard}/>
                </Suspense>

                <Suspense fallback='Loading...'>
                <Route path='/login' component={Login} />
                </Suspense>

                <Suspense fallback='Loading...'>
                  <Route path='/signup' component={SignUp} />
                </Suspense>

              </Switch>

            </AnimatePresence>

          </div>

          <Footer/>
          
        </div>
        
      
    );
    
  //}

}
  
export default App;

【问题讨论】:

    标签: reactjs routes lazy-loading framer-motion page-transition


    【解决方案1】:

    为未来读者解答问题

    在查看了大量资源和其他教程后,我找到了解决问题的方法。

    简而言之,我决定在 Route 标签调用的每个组件中延迟加载,而不是在“App.js”中的 Routes 处延迟加载组件(如上面问题中的代码所示)。这是有效的,因为这些路由实际上会根据用户的屏幕宽度加载非常具体的页面(请参阅下面的示例代码以获取我的注册页面):

    延迟加载之前的SignupComponent.js

    import * as React from 'react';
    import { useState, useEffect } from 'react';
    
    import { connect } from 'react-redux'; //The library that holds react and redux together.
    import { Redirect } from 'react-router-dom'; //Used to redirect logged out users to a different page.
    import '../authorization.css'
    
    //Page Transition imports
    import { PageTransition } from '../../layout/PageTransition';
    import {motion} from 'framer-motion';
    
    
    import SignupFullscreen from './SignupFullscreen';
    import SignupSmallFullscreen from './SignupSmallFullscreen';
    import SignupTablet from './SignupTablet';
    import SignupSmallTablet from './SignupSmallTablet';
    import SignupMobile from './SignupMobile';
    
    
    const SignupComponent = (props) => {
    
    
        const { authToken, auth } = props
    
       
        //Using the useWindowSize function to determine width of screen.
        let [width] = useWindowSize();
    
    
     
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //FULLSCREEN.
        if(width >= 1425){
    
            return(
                <motion.div exit='exit' variants={PageTransition} initial='hidden' animate='show'>
                    <SignupFullscreen/>
                </motion.div>
            );
        }
    
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //SMALL FULLSCREEN.
        else if( (width>1100)&&(width<=1425) ){
            return(
                <motion.div exit='exit' variants={PageTransition} initial='hidden' animate='show'>
                    <SignupSmallFullscreen/>
                </motion.div>
    
            );
    
        }
    
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //FULL TABLET SCREEN.
        else if( (width>650)&&(width<=1100) ){
            return(
    
                <motion.div exit='exit' variants={PageTransition} initial='hidden' animate='show'>
                    <SignupTablet/>
                </motion.div>
    
            );
    
        }
    
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //HALF TABLET SCREEN.
        else if( (width>425)&&(width<=650) ){
            return(
    
                <motion.div exit='exit' variants={PageTransition} initial='hidden' animate='show'>
                    <SignupSmallTablet/>
                </motion.div>
    
            );
    
        }
    
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //MOBILE SCREEN.
        else if( width<=425 ){
            return(
    
                <motion.div exit='exit' variants={PageTransition} initial='hidden' animate='show'>
                    <SignupMobile/>
                </motion.div>
    
            );
    
        }
    
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //DEFAULT IS FULLSCREEN
        else {
            return(
    
                <motion.div exit='exit' variants={PageTransition} initial='hidden' animate='show'>
                    <SignupFullscreen/>
                </motion.div>   
    
            );
        }
    
    }
    
    const mapStateToProps = (state) => {
    
        return {
            authToken: state.auth.authToken,
            authError: state.auth.authError,
            auth: state.firebase.auth
    
        }
    }
    
    const mapDispatchToProps = (dispatch) => {
        
        return {
    
        }
    
    }
    
    //Used to determine width of the screen.
    function useWindowSize() {
        const [size, setSize] = useState([window.innerWidth]);
        useEffect(() => {
            const handleResize = () => {
                setSize([window.innerWidth]);
    
            };
            window.addEventListener("resize", handleResize);
            return () => {
                window.removeEventListener("resize", handleResize);
            }
    
        }, []);
        return size;
    
    }
    
    
    export default connect(mapStateToProps, mapDispatchToProps)(SignupComponent)
    

    要引入延迟加载,您只需将这些组件中的每一个包装在 标记中,如下面的代码所示。

    添加延迟加载后的SignupComponent.js

    import * as React from 'react';
    import { useState, useEffect } from 'react';
    
    import { connect } from 'react-redux'; //The library that holds react and redux together.
    import { Redirect } from 'react-router-dom'; //Used to redirect logged out users to a different page.
    import '../authorization.css'
    
    //Page Transition imports
    import { PageTransition } from '../../layout/PageTransition';
    import {motion} from 'framer-motion';
    
    
    const SignupComponent = (props) => {
    
        const SignupFullscreen = React.lazy(() => import('./SignupFullscreen'));
        const SignupSmallFullscreen = React.lazy(() => import('./SignupSmallFullscreen'));
        const SignupTablet = React.lazy(() => import('./SignupTablet'));
        const SignupSmallTablet = React.lazy(() => import('./SignupSmallTablet'));
        const SignupMobile = React.lazy(() => import('./SignupMobile'));
        const { authToken, auth } = props
       
    
    
        //Using the useWindowSize function to determine width of screen.
        let [width] = useWindowSize();
    
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //FULLSCREEN.
        if(width >= 1425){
    
            return(
                <React.Suspense fallback={<p>Loading list...</p>}>
                    <motion.div exit='exit' variants={PageTransition} initial='hidden' animate='show'>
                        <SignupFullscreen/>
                    </motion.div>
                </React.Suspense>
            );
        }
    
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //SMALL FULLSCREEN.
        else if( (width>1100)&&(width<=1425) ){
            return(
                <React.Suspense fallback={<p>Loading list...</p>}>
                    <motion.div exit='exit' variants={PageTransition} initial='hidden' animate='show'>
                        <SignupSmallFullscreen/>
                    </motion.div>
                </React.Suspense>
            );
    
        }
    
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //FULL TABLET SCREEN.
        else if( (width>650)&&(width<=1100) ){
            return(
                <React.Suspense fallback={<p>Loading list...</p>}>
                    <motion.div exit='exit' variants={PageTransition} initial='hidden' animate='show'>
                        <SignupTablet/>
                    </motion.div>
                </React.Suspense>
            );
    
        }
    
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //HALF TABLET SCREEN.
        else if( (width>425)&&(width<=650) ){
            return(
                <React.Suspense fallback={<p>Loading list...</p>}>
                    <motion.div exit='exit' variants={PageTransition} initial='hidden' animate='show'>
                        <SignupSmallTablet/>
                    </motion.div>
                </React.Suspense>
            );
    
        }
    
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //MOBILE SCREEN.
        else if( width<=425 ){
            return(
                <React.Suspense fallback={<p>Loading list...</p>}>
                    <motion.div exit='exit' variants={PageTransition} initial='hidden' animate='show'>
                        <SignupMobile/>
                    </motion.div>
                </React.Suspense>
            );
    
        }
    
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //DEFAULT IS FULLSCREEN
        else {
            return(
                <React.Suspense fallback={<p>Loading list...</p>}>
                    <motion.div exit='exit' variants={PageTransition} initial='hidden' animate='show'>
                        <SignupFullscreen/>
                    </motion.div>   
                </React.Suspense>
            );
        }
    
    }
    
    const mapStateToProps = (state) => {
    
        return {
            authToken: state.auth.authToken,
            authError: state.auth.authError,
            auth: state.firebase.auth
    
        }
    }
    
    const mapDispatchToProps = (dispatch) => {
        
        return {
    
        }
    
    }
    
    //Used to determine width of the screen.
    function useWindowSize() {
        const [size, setSize] = useState([window.innerWidth]);
        useEffect(() => {
            const handleResize = () => {
                setSize([window.innerWidth]);
    
            };
            window.addEventListener("resize", handleResize);
            return () => {
                window.removeEventListener("resize", handleResize);
            }
    
        }, []);
        return size;
    
    }
    
    
    export default connect(mapStateToProps, mapDispatchToProps)(SignupComponent)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-16
      • 1970-01-01
      • 1970-01-01
      • 2019-11-22
      • 2020-12-28
      • 1970-01-01
      • 1970-01-01
      • 2022-01-13
      相关资源
      最近更新 更多