Динамический импорт перехватчиков реакции

Можем ли мы динамически импортировать хуки на основе значения, переданного компоненту?

Например,

App.js

<BaseComponent isActive />

BaseComponent.js

if(props.isActive) {
  // import useActive (custom Hook)
}

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


person priyanshu sinha    schedule 10.06.2020    source источник
comment
Посмотрите эту ветку: stackoverflow.com/questions/36367532/   -  person Gh05d    schedule 10.06.2020
comment
Здесь я вижу, что isActive всегда истинно, поэтому нет смысла импортировать его условно. А если свойство не всегда истинно, вы должны импортировать useActive на верхнем уровне.   -  person Siraj Alam    schedule 10.06.2020


Ответы (2)


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

См. Правила хуков.

Вызывайте хуки только на верхнем уровне. Не вызывайте хуки внутри циклов, условий или вложенных функций.

Если вы хотите условно использовать ловушку, используйте условие в его реализации ( посмотрите, например, skip вариант useQuery хука из клиента Apollo GraphQL).

const useActive = (isUsed) => {
  if (isUsed) {
    // logic
  }
}
person Dennis Vash    schedule 10.06.2020
comment
Не повлияет ли это на размер BaseComponent, который вообще не требовал useActive, если props.isActive ложно? - person priyanshu sinha; 10.06.2020
comment
Это добавит несколько байтов к размеру файла, но почему вы вообще учитываете это? Кроме того, у вас нет других вариантов, поскольку вы ограничены React API. Прочтите: stackify.com / Преждевременная оптимизация-зло - person Dennis Vash; 10.06.2020

Вы должны извлечь логику внутри ловушки useActive и динамически импортировать ее вместо динамического импорта ловушки, поскольку вы не должны вызывать ловушки внутри циклов, условий или вложенных функций. Checkout Правила хуков:

Допустим, ваш хук useActive пытался обновить заголовок документа (в реальном мире это должен быть большой фрагмент кода, который вы бы рассмотрели при использовании динамического импорта)

Это может быть реализовано следующим образом:

// useActive.js

import { useEffect } from "react";    
export function useActive() {
  useEffect(() => {
    document.title = "(Active) Hello World!";
  }, []);
}

И вы пробовали использовать его в BaseComponent:

// BaseComponent.js

function BaseComponent({ isActive }) {
  if (isActive) { // <-- call Hooks inside conditions ❌
    import("./useActive").then(({ useActive }) => {
      useActive();
    });
  }
  return <p>Base</p>;
}

Здесь вы нарушили правило «не вызывайте ловушки внутри условий» и получите Invalid hook call. ошибку.

Поэтому вместо динамического импорта ловушки вы можете извлечь логику внутри ловушки и динамически импортировать ее:

// updateTitle.js

export function updateTitle() {
  document.title = "(Active) Hello World!"
}

И вы делаете isActive проверку внутри хука:

// BaseComponent.js

function BaseComponent({ isActive }) {
  useEffect(() => {
    if (!isActive) return;

    import("./updateTitle").then(({ updateTitle }) => {
      updateTitle();
    });
  }, [isActive]);

  return <p>Base</p>;
}

Работает нормально, не нарушая никаких правил хуков.

Я прикрепил CodeSandbox, чтобы вы могли поиграть:

 Изменить hardcore-wing-p3uvc

person Hangindev    schedule 10.06.2020
comment
Это против правил крючков. - person Siraj Alam; 10.06.2020
comment
В каком смысле? Здесь не используются ловушки внутри циклов, условий или вложенных функций. - person Hangindev; 10.06.2020
comment
Не вызывайте хуки из обычных функций JavaScript. Поэтому импорт его в обычном обратном вызове и его использование там нарушит указанное выше правило. См. responsejs.org/docs/hooks-rules.html. - person Siraj Alam; 10.06.2020
comment
Здесь я импортирую не функцию перехвата, а извлеченную логику внутри исходного перехвата. - person Hangindev; 10.06.2020
comment
В любом случае внутри обратного вызова используется ловушка. - person Siraj Alam; 10.06.2020
comment
Привет, Сирадж, мой ответ может быть неясным и вызвать недоразумение. Я подробно изложил свое объяснение. Не могли бы вы взглянуть и сообщить мне, что вы думали? Заранее спасибо! - person Hangindev; 10.06.2020
comment
Позвольте нам продолжить это обсуждение в чате. - person Hangindev; 10.06.2020