Реагируйте на отложенную загрузку маршрутов с переходами между страницами
Ищите решение этой проблемы вверх, вниз и в сторону.
Моя цель - назначить отложенную загрузку почти всем компонентам на моем веб-сайте 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)