React.lazy и React.Suspense

Функция React.lazy позволяет рендерить динамический импорт как обычный. Проще говоря, она позволяет загружать дополнительные компоненты в наш общий файл bundle (для браузера) только тогда, когда они понадобятся. Это дает возможность облегчить загрузку страницы сразу, но с другой стороны увеличивает ожидание, когда приходит время подгрузки. Поэтому тут важно построить “цепочку поведения пользователей” и правильно разделить компоненты на “пачки”.

Suspense (“задержка”) позволяет показать запсное содержание, пока подгружается компонента черзе React.lazy.

ДОКУМЕНТАЦИЯ

Использование

  1. Меняем обычный импорт на импорт с “ленивой загрузкой”. Например, отложим загрузку двух компонент в файле App.js.
    Было:

    import DialogsContainer from './components/Dialogs/DialogsContainer';
    import ProfileContainer from './components/Profile/ProfileContainer';
    
    ....

    Стало:

    const DialogsContainer = React.lazy(() => import('./components/Dialogs/DialogsContainer'));
    const ProfileContainer = React.lazy(() => import('./components/Profile/ProfileContainer'));

     

  2. Теперь сами ленивые компоненты в том же файле нам в месте вызова нужно обернуть в компоненту Suspense, которая позволяет нам показать запасное содержимое (например, индикатор загрузки) пока происходит загрузка ленивой компоненты. Сам компонент Suspense можно разместить где угодно выше над этими компонентами. Например:
    return (
          
            <div className="app-wrapper">
              <HeaderContainer />
              <Navbar />
              <div className="app-wrapper-content">
                <Suspense fallback={<Preloader />}> //вот начало оборачивания
                  <Route path='/dialogs' render={ () => <DialogsContainer /> } />
                 <Route path='/profile/:userId?' render={ () => <ProfileContainer /> } />
                </Suspense>
                  <Route path='/users' render={ () => <UsersContainer /> } />
                  <Route path='/news' render={ () => <News /> } />
                  <Route path='/music' render={ () => <Music /> } />
                  <Route path='/setings' render={ () => <Setings /> } />
                  <Route path='/login' render={ () => <Login /> } />
              </div>
            </div>
        );

     

  3. Можна в качестве альтернативы создать подобие ХОКа, как показывал Димыч у видео. Для этого создаем файл src/components/hoc/withSuspense.js:
    import React, { Suspense } from 'react';
    import Preloader from '../common/Preloader/Preloader';
    
    export const withSuspense = (Component) => {
    
    
        return (props) => {
            return  <Suspense fallback={<Preloader />}>
                <Component {...props} />
                </Suspense>
        }
    
    }

     

  4. И теперь оборачиваем те же наши компоненты этим ХОКом, а не самой компонентой Suspense:
    return (
         
           <div className="app-wrapper">
             <HeaderContainer />
             <Navbar />
             <div className="app-wrapper-content">
                 <Route path='/dialogs' render={ withSuspense(DialogsContainer) } /> //вот
                 <Route path='/profile/:userId?' render={ withSuspense(ProfileContainer) } /> //и вот
                 <Route path='/users' render={ () => <UsersContainer /> } />
                 <Route path='/news' render={ () => <News /> } />
                 <Route path='/music' render={ () => <Music /> } />
                 <Route path='/setings' render={ () => <Setings /> } />
                 <Route path='/login' render={ () => <Login /> } />
             </div>
           </div>
       );

    Хотя так вроде выглядит похуже, имхо.

ПРЕДОСТЕРЕЖЕНИЕ: Если Suspense используется вместо со Switch, то для нормальной работы Suspense должен находиться за пределами Switch. Например:

<Switch>
<Route path='/' exact={true}  render={() =>  'Введите номер автомобиле в поле выше, чтобы пробить его по базе.'} />
<Route path='/number/:number?' render={() =>  <ResultCheckNumberContainer />} />
<Route exact path='/make/:make' render={() => <CarsListContainer />} />
<Route path='/make/:make/:model' render={() => <OneModelContainer />} />
<Route path='/' component={NotFound} />
</Switch>
</Suspense>

Если сделать наоборот, то пока грузится компонента внутри Switch, будут отображаться те компоненты, которые идут ниже неё. Хотя после окончания загрузки отображаться будет только нужная.

Как проверить работу?

Увидеть эту подгрузку и протестировать можно через вкладку Network консоли во время перехода на ту компоненту, которая должна подгрузиться.

Проверка работы React.lazy

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *