Когда и как выбирать между React Hooks и прохождением старых HOC-реквизитов?
До сих пор мы привыкли к потоку потоков, когда данные вводились в компонент через подпорки. Таким образом, вы можете посмотреть на сигнатуру Props и посмотреть, каковы требования к компонентам.
Хуки - это удивительная особенность, но когда мы перейдем к ним, я обнаружу, что они предоставляют еще один вход для зависимостей, которыми сложнее управлять, так как вам нужно посмотреть на реальный код компонента, чтобы увидеть его.
Конечно, мы можем использовать крючки только в контейнерных компонентах, но я чувствую, что некоторые из их основных достоинств - это способность уменьшать вложенность и HOC.
Каковы лучшие практики (в настоящее время) для решения, какой компонент должен использовать ловушку, а какой должен использовать реквизит рендеринга?
4 ответа
Крючки и HOCs - это разные модели программирования, и их сравнение будет похоже на сравнение апельсинов и яблок.
TL; DR
Как правило, я использую HOC, когда хочу условного рендеринга компонентов (если условие: рендеринг A, иначе рендеринг B), в противном случае я использую хуки. Это только мое мнение.
За и против:
HOCs Pros
- Легко отделить всю логику от компонента пользовательского интерфейса (см. " Перекомпоновать").
- Легко сочинять.
- Управлять компонентом перед любым рендерингом.
HOCs Минусы
- Столкновения с именами - 2 HOC могут использовать и устанавливать опоры с одинаковыми именами.
- Реакт дом гигантский.
- Каждое изменение в родительских реквизитах заставляло детей перерисовываться - это поведение по умолчанию в React, но когда у нас много HOC, мы должны быть очень осторожны.
- Типы. С точки зрения компонентов трудно понять, какие реквизиты и типы мы получаем.
- Использование HOC передаст все реквизиты ребенку, даже если ребенку из этого конкретного HOC требуется только опора
x
, - Процесс использования аргумента, который зависит от реквизита компонента для HOC, может быть сложным
HOCs Pro & Con оба
- Нет необходимости определять переменные, просто оберните с помощью HOC, и вы получите реквизиты, которые поставляет HOC - что заставляет наш UI-компонент "угадывать" имена реквизитов.
Крючки Плюсы
- Читаемый и декларативный.
- Производительность - обновляется только при смене конкретных реквизитов.
- Растущее сообщество.
Крючки Минусы
- Только внутри компонента - это означает, что не может визуализировать компонент при условии, что пропущены реквизиты.
- Гигантские файлы компонентов, которые содержат пользовательский интерфейс и логику в целом.
Хуки все еще находятся в альфа-версии, и поддержка devTools все еще находится в стадии разработки. И в соответствии с React FAQ хуки могут использоваться как альтернатива renderProps и HOC, но могут сосуществовать с ними
Зачастую реквизиты рендеринга и компоненты высшего порядка отрисовывают только одного дочернего элемента. Мы думаем, что крючки - более простой способ обслуживания этого варианта использования. Для обоих шаблонов все еще есть место (например, у компонента виртуальной скроллера может быть свойство renderItem или у компонента визуального контейнера может быть своя собственная структура DOM). Но в большинстве случаев крючков будет достаточно и они могут помочь уменьшить вложение в вашем дереве.
Хуки допускают логику с сохранением состояния в функциональных компонентах и аналогичны компонентам класса в React.
С хуками сложнее управлять, так как вам нужно посмотреть на код компонента, чтобы увидеть его.
Не совсем, поскольку вы можете извлекать пользовательскую логику, которая есть в ваших HOC или renderProps в пользовательском хуке, и искать ее реализацию вместо понимания того, что на самом деле происходит в реальном компоненте.
HOC - это своего рода АОП, АОП может решать сквозные проблемы.
React Hooks не является АОП, из Rules of Hooks хуки можно использовать только следующими способами:
- Вызывать хуки из функциональных компонентов React.
- Вызов хуков из пользовательских хуков
Оба они следуют шаблону проектирования разделения проблем.
Реагирующие хуки предоставляют хук жизненного цикла компонента, поэтому вы можете создавать повторно используемые пользовательские хуки на основе хука жизненного цикла компонента.
HOC более гибкий, из документа:
Возможно, вы заметили сходство между HOC и шаблоном, называемым компонентами-контейнерами. Компоненты контейнера являются частью стратегии разделения ответственности между задачами высокого и низкого уровня. Контейнеры управляют такими вещами, как подписки и состояние, и передают реквизиты компонентам, которые обрабатывают такие вещи, как рендеринг пользовательского интерфейса. HOC используют контейнеры как часть своей реализации. Вы можете думать о HOC как о параметризованных определениях компонентов контейнера.
И давайте использовать пример, чтобы объяснить сквозные проблемы.
Если у вас есть повторно используемый пользовательский крючок реакции с именем , и у вас есть десять компонентов, они будут использовать его. Вам нужно импортировать и вызывать хук десять раз.
Теперь вы создаете HOC с именем
HOC также является реактивным компонентом. Если мы поместим слишком много логики кода в HOC, он не будет следовать шаблону проектирования разделения задач. Таким образом, мы можем создать несколько пользовательских хуков для инкапсуляции различной логики.
Так что, на мой взгляд, если есть более 3 компонентов, использующих одну и ту же логику, я буду использовать пользовательский хук HOC + react.
HOC помогает мне решить проблемы с повторяющимся импортом и вызовами в каждой проблеме компонента, упомянутой выше. Пользовательский хук React помогает мне разделить компоненты и логику.
HOC и реактивные хуки не конфликтуют, их следует использовать в комбинации.
Пример:
import React, { useCallback, useMemo, useState } from 'react';
const MaskContext = React.createContext({ visible: false, show: () => {}, hide: () => {} });
// Abstract a "mask" view model using a react custom hook.
const useMask = () => {
const [state, setState] = useState(false);
const hide = useCallback(() => setState(false), [setState]);
const show = useCallback(() => setState(true), [setState]);
return useMemo(() => ({ visible: state, show, hide }), [state, show, hide]);
};
// HOC, pass the context value to the wrapped component without modifying it.
const WithMask = (WrappedComponent) => {
const mask = useMask();
return () => (
<MaskContext.Provider value={mask}>
<MaskContext.Consumer>{(value) => <WrappedComponent mask={value} />}</MaskContext.Consumer>
</MaskContext.Provider>
);
};
const MyComp = ({ mask }) => {
return <button onClick={mask.show}>click me!</button>;
};
const MyCompWithMask = WithMask(MyComp);
const App = () => {
return <MyCompWithMask />;
};
Я часто вижу, что в компоненте используются хуки с побочными эффектами. Это затрудняет тестирование вашего компонента и не подходит для хуков imho.
Например, вы создаете компонент с некоторыми настраиваемыми const {data, loading, error} = useFetch(endpointUrl)
а затем напрямую использовать его в части рендеринга return <>{data.name}</>
того же компонента.
Для меня это все еще вариант использования HOC. Загрузите данные в HOC, предоставьте их в качестве свойств вашему компоненту дампа. Таким образом, вы сможете легче протестировать компонент и при этом разделить проблемы.