Реагируйте на отложенную загрузку маршрутов с переходами между страницами

Ищите решение этой проблемы вверх, вниз и в сторону.

Моя цель - назначить отложенную загрузку почти всем компонентам на моем веб-сайте React. Однако эти компоненты используют переходы между страницами кадра и движением при входе и выходе компонентов. Комбинация переходов между страницами и отложенной загрузки приводит к тому, что компонент больше не загружается должным образом при нажатии на него в качестве маршрута.

Я нашел вдохновение в этом сообщении (https://github.com/reactjs/react-transition-group/issues/580) и попытался представить пакет «response-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;

1 ответ

Решение

ОТВЕТ НА ПРОБЛЕМУ ДЛЯ БУДУЩИХ ЧИТАТЕЛЕЙ

Изучив многочисленные источники и другие руководства, я нашел решение возникшей у меня проблемы.

Короче говоря, вместо компонентов отложенной загрузки на маршрутах в «App.js» (как видно из кода в вопросе выше) я решил выполнять отложенную загрузку внутри каждого компонента, который вызывает тег маршрута. Это работает, потому что эти маршруты фактически переходят к компонентам, которые загружают очень конкретные страницы в зависимости от ширины экрана пользователя (см. Пример кода ниже для моей страницы регистрации):

RegistrationComponent.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)

Чтобы ввести отложенную загрузку, вы просто заключите каждый из этих компонентов в тег <React.Suspense>, как показано в приведенном ниже коде.

RegistrationComponent.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)
Другие вопросы по тегам