Как Прекратить Перенаправление Моей Страницы С Помощью Динамического Импорта?

#javascript #reactjs #react-redux

Вопрос:

Для своей домашней страницы я пытаюсь использовать загружаемые компоненты с наблюдателем пересечения. Когда мой магазин redux обновляется, вся страница обновляется заново. Как я могу этого избежать?

 import React from "react"
import loadable from "@loadable/component"
import { useSelector } from "react-redux"

const Index = () => {
const intersectState = useSelector(state => state.intersectState)

const BannerProducts = loadable(() =>
    import("../components/bannerProducts/bannerProducts")
  )
const SellingBulletPoints = loadable(() =>
    import("../components/sellingBulletPoints/sellingBulletPoints")
  )

const Category = intersectState.categoryComponent amp;amp;
loadable(() => import("../components/category/category"))

return (
<>
  <BannerProducts />
  <SellingBulletPoints />
  {intersectState.categoryComponent amp;amp; <Category />}
</>
 )
}

export default Index
 

Комментарии:

1. Используйте useMemo или используйте useCallBack , чтобы остановить повторную передачу. Я думаю, что эта ссылка поможет вам kentcdodds.com/blog/usememo-and-usecallback или, если вы хотите ознакомиться с официальной документацией, пожалуйста, посетите эту страницу also.reactjs.org/docs/hooks-reference.html#usememo


Ответ №1:

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

Это происходит потому, что ваши компоненты переопределяются при каждом рендеринге.

Если вы переместите эти определения компонентов ленивой загрузки за пределы функции визуализации, то это должно работать нормально.

 const BannerProducts = loadable(() =>
    import("../components/bannerProducts/bannerProducts")
  )
const SellingBulletPoints = loadable(() =>
    import("../components/sellingBulletPoints/sellingBulletPoints")
  )

const Category = loadable(() => import("../components/category/category"))
 

Вот как это работает:

loadable(()=>import('./component')) Вызов создает только компонент-оболочку, который при визуализации приостанавливается (или просто становится нулевым) до тех пор, пока полный код не будет в браузере и готов к запуску. До тех пор, пока этот компонент не будет отрисован, код разделения кода не загружается в браузер.

Таким образом, воссоздавая компонент оболочки с ленивой загрузкой, вы ничего не делаете, кроме добавления дополнительных циклов. Фактически, вы уничтожаете то, что использует React, чтобы определить, является ли визуализируемый элемент тем же самым (т. Е. Component===Component ). Таким образом, при каждом повторном отображении родительского элемента ваш компонент-оболочка с отложенной загрузкой создается заново, что приводит к его отключению/повторному подключению.

К счастью, отложенная загрузка достаточно оптимизирована, так что она загружает один и тот же фрагмент только один раз — при первом отображении компонента с отложенной загрузкой (отсюда import('./component') и строка).

Чтобы понять, как это работает и почему ваш компонент перемонтируется, я создал песочницу кода с 3 компонентами, все с одним и тем же кодом (хотя и с разными именами и строками).

 import { useEffect } from "react";
console.log("CodeSplit Code loaded!");
export default function CodeSplit() {
  useEffect(() => {
    console.log(`CodeSplit Mounted`);
    return () => {
      console.log(`CodeSplit Unmounted`);
    };
  }, []);
  return <div>CodeSplit</div>;
}
 

Если вы запустите codesandbox, эти три компонента:
NormalCode — Код, отображаемый синхронно как часть базового пакета. NormalCode Code Loaded Сообщение регистрируется по мере выполнения кода при загрузке основного пакета.

CodeSplit — Код лениво загружается с использованием loadable , но в правильном способе его использования. CodeSplit Code Loaded Сообщение регистрируется, как только show splits нажата кнопка. Это происходит потому, что это первый раз CodeSplit , когда лениво загруженный компонент отображается, даже если <CodeSplit /> он находится в вызове. При этом, когда он отображается и вы вводите данные, больше нет никаких CodeSplit Mounted сообщений и CodeSplit Unmounted сообщений.

CodeSplitGoofed — Код загружается с loadable задержкой , но компонент с отложенной загрузкой создается в App рендеринге компонента. Это происходит так же, как CodeSplit и для аспектов отложенной загрузки, но когда вы вводите данные во входные данные, из журналов CodeSplitGoofed Mounted и консоли видно CodeSplitGoofed Unmounted , что этот компонент размонтируется и перемонтируется каждый раз при повторной App отрисовке компонента. Причина этого такова, как указано выше — React не может знать, что это тот же компонент, что и раньше.

https://codesandbox.io/s/so-stop-react-rerendering-page-with-dynamic-import-mch7g?file=/src/App.js

Комментарии:

1. На самом деле я напечатал это неправильно… Смотрите выше. Проблема в том, что intersectState.categoryКомпонент также должен быть в определениях компонентов. Я хочу сказать… если состояние в redux обновлено… найдите JS для этого компонента и отрисовайте его, не обновляя всю страницу.

2. Нет никакой разницы в функциональности того, что я предложил, по сравнению с тем, что вы отредактировали. Если вы динамически не импортируете другой Category компонент с другого пути (в этом случае удачи с webpack…), позвольте компонентам ленивой загрузки делать свое дело. Вам не нужно каждый раз заново создавать лениво загруженный компонент; просто динамически визуализируйте компонент. Воссоздание компонента заставит React каждый раз думать, что это совершенно другой компонент. Таким образом, он потеряет все внутреннее состояние, так как предыдущий будет размонтирован, а новый будет смонтирован.

3. Разница в том, что const Category = intersectState.categoryComponent amp;amp; загружаемый(() => импорт(«../компоненты/категория/категория»)) загружает javascript только в том случае, если состояние redux говорит, что оно еще не загружено наблюдателем пересечения. Если я удалю проверку состояния, то он загрузит JS при загрузке страницы, даже если пользователь не перейдет к компоненту. Я просто пытался вырезать JS и загружать его только тогда, когда пользователь нажимает на этот компонент.

4. @JasonBiondo Я обновил свой ответ примером и большим количеством описания, чтобы помочь вам понять, как работает ленивая загрузка.