Pull to refresh

Comments 49

Хоть я сейчас плотно сижу на Vue, но с появлением Hooks начал опять поглядывать в сторону React :)
Понятно, что у Vue это все еще только в наметках и вариациях, но судя по тому, что есть, в Реакте это более логичное и законченное решение. Пока что ;)
Хуки очень круты, но почему все сравнивают с HOC? HOC же аналог декоратора для компонента. Он имеет очень классную особенность — позволяет менять поведение в рантайме и не трогать код основного компонента, тем самым не нарушив работу компонента во всём проекте, а может даже и нескольких. Иногда это жизненно необходимо.

Почему нельзя совмещать хуки и хоки? Просто нужно без фанатизма. Это не противостояние за власть, а разные инструменты для разных задач. Я как бы понимаю, что и микроскопом можно гвозди забивать, но лучше забивать гвозди молотком, а с микроскопом делать другое.
Я как бы понимаю, что и микроскопом можно гвозди забивать, но лучше забивать гвозди молотком, а с микроскопом делать другое.

Забавно, что вся история с хуками начинается как раз с забивания гвоздей чем угодно кроме молотка — если при проектировании интерфейса не смешивать модель с представлением, то хуки особо и не сдались (потому что представляют собой всего лишь более сильный инструмент для отделения модели и её логики от представленческих вещей типа цикла жизни компонент). Но поскольку модель и логика у фронтэндщиков частенько очень простая и вырожденная — оные фронтэндщики очень любят вписать её сразу в компоненты, а уже потом начать думать, что же с этим делать. И вот тут-то и хуки становятся полезными.
Балом правят паттерны (в прочем как и везде).
Захотел разделения бизнес логики и представления — используешь паттерн Container Component. Захотел изменить что-то в одном месте не меняя поведение в других — HOC. Захотел всё смешать в кучу — написал через хуки.

Только везде учат, что паттерны должны быть к месту, а не ради использования паттернов, но в React какой-то хайп идёт по каждому новому паттерну (или функционалу, который именуют очередным убийцей). То HOC самый лучший паттерн, который заменяет почти всё, потом появился убийца HOC'а — Render Props, а теперь уже и хуки, которые опять же сравнивают на полном серьёзе с HOC и Render Props как их замену.
Такое ощущение, что все просто поклоняются тому, о чём пишет Дэн Абрамов. Он написал, что HOC лучший — все это подхватили. Он написал, что HOC ужасен и Render Props теперь лучший — всё форсят Render Props.

Видимо молодость фронтенда даёт о себе знать. Когда-нибудь большая часть паттернов устаканится и их правильное применение осядет в головах, как это происходит в бэкенде. А сейчас идёт поиск серебряной пули.
Захотел разделения бизнес логики и представления — используешь паттерн Container Component.

Это шаг один. На шаге два обычно приходит понимание, что модель и логика — она вообще не обязана относиться к компонентам и уж тем более реакту: это просто код, ему пофиг на эти ваши фреймворки и либы по большей части, он и в реакте, и в ангуляре, и в чем угодно вообще будет выглядеть примерно одинаково с поправками на интеграционные рюшечки с представлением.

Во фронтэнде слишком часто встречается проталкивание инструмента везде, где только можно, даже если он не нужен. Есть реакт и его компоненты? А давайте у нас всё-всё будет «компонентом», даже если объективно это вообще ни разу не компонент? А давайте!

Это вот вообще классическое «когда у вас в руках молоток, все проблемы выглядят незабитыми гвоздями».

В клиентском коде логика представления очень часто неотделима от компонента, и кроме как в нем больше нигде не нужна, если мы не говорим о какой-то сложной бизнес логике. Пример — какой-нибудь разворачивающийся блок, выпадающее меню, кнопка со спиннером. Если такую логику начинать выносить — оно вроде как правильно с точки зрения паттернов, но выглядит крайне монструозно. Если слепо всем паттернам следовать — получается Java которую невозможно без крови в глазах читать от словоблудия. JS тем и хорош и элегантен, что можно write less do more. За это надо платить. И это риск. Главное головой думать и баланс соблюдать между "как надо" и "как проще".


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

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

Смысл не в том, что она нужна где-то еще, смысл в том, чтобы не было мешанины, которую потом трудно поддерживать. В фреймворках с темплейтами отсутствие мешанины форсится самим фреймворком, то есть намешать нельзя by design. В случае реакта намешать можно, по-этому изобретаются способы, как этого не делать — smart/dumb компоненты, рендер пропсы, хуки вот и так далее.

В Angular в темплейте будь здоров можно логики намешать, впрочем, как и везде.


HOC, RP и Hooks не просто про разделение, а про возможность выделить некий код как общий и переиспользовать его. Это библиотечные вещи в первую очередь, как подключить что-то внешнее к компоненту. А как ворочать локальным стейтом — дело десятое, если этого нигде снаружи не видно.

В Angular в темплейте будь здоров можно логики намешать, впрочем, как и везде.

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


HOC, RP и Hooks не просто про разделение, а про возможность выделить некий код как общий и переиспользовать его. Это библиотечные вещи в первую очередь, как подключить что-то внешнее к компоненту.

Нет, это в первую очередь про то, как отделить то самое "внешнее" от самого компонента.

набор конструкций, которые можно использовать в темплейте, существенно ограничен

Знаете сколько диких конструкций с пайпом и наворотами я видел в ngFor https://angular.io/api/common/NgForOf#local-variables. Я не спорю, что с темплейтом прострелить себе ногу сложнее, но зато и выразительность хуже, в JSX можно очень красивые вещи делать, если с умом подходить.


не просто про разделение, а про возможность выделить некий код как общий и переиспользовать его
в первую очередь про то, как отделить то самое "внешнее" от самого компонента

Вы по-моему то же самое написали, но другими словами. У меня акцент на то, что само по себе выделение должно быть оправдано и должно служить некой цели. Если компонент вещь в себе и логика его никому более не нужна — нет смысла что-то из него выделять в HOC/RP/Hook. Выделять имеет смысл то, что можно переиспользовать.

Знаете сколько диких конструкций с пайпом и наворотами я видел в ngFor https://angular.io/api/common/NgForOf#local-variables.

Так это и есть элементарные конструкции, не содержащие какой-либо логики, с которыми нет никаких проблем.


но зато и выразительность хуже, в JSX можно очень красивые вещи делать, если с умом подходить.

Эти "красивые вещи" как раз то, чего не должно быть в логике рендера, так что ничего красивого в них на самом деле нет.
Рендер должен иметь только одна ответственность — с-но, рендерить. В случае templatye-based подхода это условие выполнено и в итоге вам достаточно краткого взгляда на темплейт, чтобы понять, что вы получите в результате рендеринга компонента. В случае реакта — у вас plain js, который может делать все что угодно, с-но, эту логику еще распарсить надо (что часто нетривиально), там же обычно происходит и обработка данных. Это не говоря уже о частом использовании антипаттернов вроде HOC/render props, когда в верстке зачем-то оказываются вещи вроде "эта компонента забирает данные оттуда", что вообще в верстке недопустимо и за что следует просто отрывать руки и вон из отрасли.


Если компонент вещь в себе и логика его никому более не нужна — нет смысла что-то из него выделять в HOC/RP/Hook.

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


Вы же понимаете что вещи вроде best preactices а-ля "не мешайте логику и вид" написаны, что называется, кровью? Все это уже было, давным-давно, и все это было вытеснено более современными и надежными подходами.


А ваша логика про "удобство" эта логика из разряда что "работать без шлема удобнее" или "солдату удобнее на посту спать". Ну с этим трудно спорить. Действительно — удобнее. Тем более что через два года с вероятностью 90% типичный фронтендщик сменит место работы и поддерживать то, что он наговнякал, ему не придется. А новый месье скажет "давайте выкинем это говно и напишем новое".

Я несколько более прагматично смотрю. Уровень темплейтов — это самый незначительный уровень в нормальном большом приложении. Все реально важные модули, где нужна архитектура — выше. Если, например, мы говорим о приложениях, которые ворочают данными, особенно в реальном времени, то там ядро данных будет скорее всего вообще ничего не знать о том Vue у вас или допустим Angular или React, потому что там MobX/Redux/RX/plain-vanilla/что-угодно. И по большому счету при правильном подходе должно быть все равно что творится в шаблонах, т.к. верстку переделывают и меняют часто, в том числе полностью с нуля, потому что последние A/B тесты показали, что как было — не годится. И за умную логику в шаблонах/компонентах вместо ядра данных — по голове дадут так и так.


Более того, работать приходится не только с мастерами экстра-класса, поэтому да, скорость разработки в формате "без шлема", а также дешевизна кода, который с большой долей вероятности будет выкинут — это крайне важные вещи.


С точки зрения "по учебнику" я с Вами согласен, но в жизни важны совсем другие вещи. Когда в системе 6000 модулей все должно быть чисто и аккуратно на многих уровнях, и если все правильно сделано на остальных уровнях, шаблон там или не шаблон в глубине уже не имеет значения.

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

Вот именно по-этому в шаблонах и не должно быть логики, все верно. Иначе переделка верстки легким движением руки превращается в полноценный рефакторинг со всеми вытекающими.

Описание классов стилей отделено от представления и css классы добавляются через атрибуты.
Некоторые jquery плагины применяют свою логику в зависимости от добавленных атрибутов. Т.е. там общая логика тоже вынесена из представления.
Разве это выглядит монструозно?
Но вместо вынесения логики представления в атрибуты у нас есть всякие миксины, hoc, теперь еще и hooks.
JustDont меня опередил)
В общем, хочу сказать следующее. Прихожу к выводу, что нынешние фронтенд фреймворки допустили общую архитектурную ошибку и предлагаются разные решения вокруг этой ошибки.
Я о разделении ответственности. Компонент занимается и логикой и отображением, что нарушает принцип единственной ответственности.

Сейчас в классе/функции пишется template/метод render. Там же пишется обработка логики.
Либо часть логики выносится в миксины, HOC, куда-то еще.
Но суть от этого не меняется. Вся эта дополнительная логика привязывается к одной сущности — компоненту, который занимается еще и отображением.
Получается, что связь между отображением и логикой — один к одному.
В итоге методы, данные, либо props так или иначе смешаны в одном компоненте.
Так же быть не должно!

Можно сделать по другому:
  • Компонент занимается только отображением.
  • В нем нет методов жизненного цикла.
  • К компоненту можно подключать сколько угодно сущностей с логикой (не знаю, как лучше назвать, поэтому пусть будет сущность с логикой), где у каждой сущности есть свое состояние и прочая логика, включая методы жизненного цикла.

И проблема с пересечением данных была бы решена и для компонентов не были бы нужны всякие миксины, HOC, Container Component и прочее. Плюс легко в рантайме можно было бы добавлять/удалять логику.
При этом аналог HOC с логикой может быть полезен, но не для обертки над компонентом, а для обертки над сущностью с логикой.
Можете привести пример построения UI и связывания с ним логики на какой-то другой платформе (другом фреймворке/языке), где, по Вашему мнению, такой архитектурной ошибки нет?
Swing, например. Удобством там часто и не пахнет, потому что очень строго MVC везде, и пропустить или упростить бойлерплейт почти нигде нельзя. Зато можно учиться тому, как вообще нормальный MVC должен выглядеть. Главное не тащить его обязаловкой во всё, в том числе и вырожденные случаи.
В чем фундаментальное отличие между
JButton button = new JButton("Button");
ActionListener actionListener = new MyActionListener();
button.addActionListener(actionListener);
и react'овским
<button onClick={handleClick} />
или angular'овским
<button (click)="onClick()">Button</button>

?
Вы намеренно приводите кусок кода, в котором нет M, да?
Я никогда не работал с Swing и привожу первый кусок кода по запросу «Java Swing». Ну хорошо, допустим что кнопка из предыдущего куска когда по клику делает что-то с данными в таблице, а сама таблица связана с моделью:
JTable table = new JTable();
Model model = new Model();
table.setModel(model);

Controller controller = new Controller(model);
button.addActionListener(controller);
а в реакте
<Table model={model} />

Вопрос остается тем же — в чем фундаментальное отличие от реакта и, особенно, от angular?
Вооот, это уже честнее. А теперь смотрите: реализовать в реакте или еще там каком ангуляре MVC — да никаких проблем (потому что ангуляры и прочие реакты это почти полностью V, остальное их не касается). Но очень часто этого не делают, и потом начинают мужественно бороться с проблемами.

Возвращаясь к вашим примерам, в реакте очень редко можно увидеть таблицу, как написано у вас, и очень часто — вот так:
<Table data={data} />

Думаю, вам понятно, чем это отличается от свинга, в котором так сделать попросту нельзя.
UI в unity3d.
Но привести прям пример UI мне сложно, искать надо.
Скажу, что UI там строится по тому же принципу, что и все остальное в проекте. Про это можно здесь почитать:
docs.unity3d.com/ru/current/Manual/GameObjects.html
docs.unity3d.com/ru/current/Manual/UsingComponents.html

Чтобы понятней было, можно еще тут про ECS почитать:
habr.com/ru/post/358108 (пункт «Что такое ECS»)
Почему нельзя, можно, только зачем? ) HOC (как и Render Prop) — это способ переиспользования логики/верстки в нескольких местах. Композиция UI представления (компоненты) — всегда была сильной стороной React. Просто выносишь в компонент и переиспользуешь. А вот чтобы шерить логику, не было простого инструмента. Для этого как раз все использовали HOC/Render Prop. Как раз hook — это новый правильный, простой «молоток» для переиспользования логики.
Но HOC и Render Props больше, чем просто способ для повторного использования кода. Во всех статьях их показывают только с одной стороны, как они ужасны по сравнению с хуками в некоторых кейсах. А потом обязательно сделают вывод, что хуки крутые, а хоки и рендер-пропсы уже прошлый век.

Покажите мне простой пример паттерна декоратор или адаптер на хуках. Покажите мне аналог scoped-slots на хуках. Окажется ли это проще, чем с HOC или Render Props?

Ну и главный вопрос. Какой из этих молотков хуки:
виды молотков
image
хук — это молоток с крючком, как картинка в статье )) я еще раз повторюсь хуки — это удобный инструмент. Появились хуки — многие вещи стало писать проще. Про scoped-slots c React это можно написать так:
const Template = ({ col1, col2 }) => (
  <div>
    {col1}
    {col2}
  </div>
);

const TemplateWithData = ({ data }) => (
  <Template col1={<div>{data.first}</div>} col2={<div>{data.second}</div>} />
);
Что-то я вчера разошёлся, видимо накипело из-за других статей по хукам.
В вашей говорится о конкретном случае использования. Для этого я бы тоже не стал использовать HOC или Render Props. Но в данном кейсе мне больше симпатизирует паттерн Container Component. Всё-таки если захотим использовать тот же компонент, но с другой логикой получения данных, то в вашем случае придётся создавать ещё один компонент, в который прокинем новый хук. В случае контейнера мы просто создаём новый контейнер, а сам компонент не трогаем. А вообще хуки — это конструкция фреймворка. Их можно совмещать со всеми паттернами, будь то HOC, Render Props, Container Component или любой другой из известных и не очень, которые мы используем для разделения зон ответственности и связанности кода.

Но касательно вашего примера — вы написали обычные слоты. Для слотов с ограниченной областью видимости как раз надо передать функцию, т.к. параметры в неё должен передать дочерний компонент. А это уже Render Props.
Это может понадобиться при создании универсальных компонентов, например, автокомплита, когда элемент списка в разных местах может иметь разный шаблон. Т.е. мы говорим, что родитель может передать кусок шаблона в дочерний компонент, но в нём можно использовать только определённый набор параметров (к примеру {id, name, title}).
я так понимаю, вы про такой вариант говорите.
const Component1 = ({ getData }) => <div>{getData(1)}</div>;
const Component2 = ({ getData }) => <div>{getData(2)}</div>;

const WrapperRenderProp = ({ children }) => {
  const DATA = [1, 2, 3, 4];
  const getData = i => DATA[i];
  return <div>{children(getData)}</div>;
};

const ResultWithRenderProp = () => (
  <WrapperRenderProp>
    {getData => (
      <div>
        <Component1 getData={getData} />
        <Component2 getData={getData} />
      </div>
    )}
  </WrapperRenderProp>
);


но это можно и так написать без renderProp
const Component1 = ({ getData }) => <div>{getData(1)}</div>;
const Component2 = ({ getData }) => <div>{getData(2)}</div>;

const WrapperWithProps = ({ Template1, Template2 }) => {
  const DATA = [1, 2, 3, 4];
  const getData = i => DATA[i];
  return (
    <div>
      <Template1 getData={getData} />
      <Template2 getData={getData} />
    </div>
  );
};

const ResultWithProps = () => (
  <Wrapper Template1={Component1} Template2={Component2} />
);


Какой подход выбрать — нужно смотреть на детали. Если, например, есть лэйаут (WrapperWithProps), который в зависимости от темы рендерит разный Template1/Template2 и передает одни и те же пропсы я бы выбрала подход WrapperWithProps.
А если надо общий JSX но при этом супер нетривиальная логика с Template внутри я бы выбрала WrapperRenderProp. Но в любом случае это имеет смысл, когда есть общая верстка-раппер (общий JSX).
Посыл в статье с хуками про то, что удобно переиспользовать логику. Если нужно переиспользовать верстку, то композиция компонентов всегда была сильной стороной React — можно по-разному.

А кто-нибудь может пояснить, какую все-таки конкретно задачу решают хуки?
Ну то есть, если нужен компонент со стейтом — мы просто делаем компонент со стейтом, и хуки не нужны (пример с useRequest на обычном стейте без хуков реализуется точно так же, допустим). Если нужен компонент без стейта — мы делаем компонент без стейта, и хуки тоже не нужны.
В каком случае они нужны? Если хотя бы теоретически представить.

Хуки не делают ничего такого, чего нельзя сделать с классами. Это просто другой путь, который команда react-а взяла как за основной. В некотором роде классы теперь legacy.
Т.е. нужны они везде где у вас stateful компоненты и вы пишете код, в поддержке и развитии которого вы заинтересованы в будущем.


Команда react-a героически победила "проблему с this", заменив её на не менее сложную проблему с оркестрированием замыканий (не очень опытным разработчикам это страшно "выносит мозг", ибо код быстро становится неочевидным). Да и опытным ребусы гадать не всегда хочется. Самое простое это setState + async-useCallback. Всякие фокусы с useRef не для domElement-ов.


Я с декабря пишу используя хуки, очень нравится. Но не могу не отметить что это уже какой-то другой react. На мой взгляд писать приложение правильно с хуками сложнее, чем с классами. Требует большей квалификации. Как-то это дисгармонирует с их политикой партии. Хотели упростить, ведь "классы это сложнааа"...

уки не делают ничего такого, чего нельзя сделать с классами. Это просто другой путь, который команда react-а взяла как за основной. В некотором роде классы теперь legacy.

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


Команда react-a героически победила "проблему с this"

Это какая именно проблема имеется в виду?


Т.е. нужны они везде где у вас stateful компоненты и вы пишете код, в поддержке и развитии которого вы заинтересованы в будущем.

То есть, фактически, разработчики реакта взяли в заложники свое комьюнити? "Используйте наш кривой костыль вместо полноценного решения, иначе поддерживать не будем"?
Фигасе.

То есть, фактически, разработчики реакта взяли в заложники свое комьюнити? «Используйте наш кривой костыль вместо полноценного решения, иначе поддерживать не будем»?

Про поддержку классов пока что везде очень осторожные высказывания, что их поддержка никуда не денется и никак не поменяется. Не думаю, что им хочется повторять историю angularJS в исполнении реакта. Никто не побежит переписывать свой код с объектной парадигмы на функциональную просто потому, что разработчикам реакта так нравится больше.
Никто не побежит переписывать свой код с объектной парадигмы на функциональную

Хуки же это наоборот объектная парадигма. С-но, к ним основная претензия как раз и состоит в том, что непонятно, зачем нужна наколеночная реализация ООП, когда она уже есть нативная. Другое дело, если бы хуки появились лет 5+ назад, когда классы были еще совсем не в моде. Тогда свои костыльные ООП-подсистемы были еще актуальны.

Не скажу за реакт, но у vue решили отказаться от реализации нативной поддержки классов для компонентов (сейчас у них через декораторы и не совсем красиво) в 3-й версии в пользу своего аналога хуков. Всё больше людей во фронте отдают предпочтение композиции вместо наследования.
Всё больше людей во фронте отдают предпочтение композиции вместо наследования.

Так с классами точно такая же композиция. Composition over inheritance — это же вообще ООП-шная придумка. Тут проблема в том, что вместо нативных, полноценных классов, которые поддерживаются на уровне языка, люди зачем-то делают свои, на коленке. Никаких разумных причин, очевидно, для этого быть не может, обычный NIH-синдром.


В результате вместо одной нативной реализации ООП, сейчас будет минимум три распространенных — нативная, реакт-хуки и вуе-хуки. И у каждой из них будет свое собственное темное прошлое, туманное будущее и мрачное настоящее.

Это какая именно проблема имеется в виду?

"this и ООП в JS это так сложно, что начинающие разработчики и не только путаются и пишут говно-код". Что-то в таком духе. ИМХО, мне было бы легче новичку объяснить что у него там с this сломалось, нежели объяснить почему в его async-callback-е не видно обновлённый state.


Фигасе

А то. Правда выпиливать классы пока никто вроде не собирается. Но каких-то заметных улучшений в этой области ждать не приходится, они хорошо дали понять, что right react way это хуки и хоки. react-team вообще тяготеет к таким вещам. Хотят везде pure-function, а где не получается, то хотя бы что-то издали похожее на pure-function :) Хотят композицию, иммутабельность, дробление и всё такое.


В целом мало-мальски сложное приложение сейчас состоит из такого разнообразного бульона подходов. И render-methods, и контекст, и классовые компоненты (error-boundaries), и слоты, и хоки, и хуки. Может ещё чего забыл. Приправьте к этому какой-нибудь redux (особенно если с proxy, селекторами, викмап-мемоизацией) или mobx и получиться того ещё монстра. Но мне нравится :)

"this и ООП в JS это так сложно, что начинающие разработчики и не только путаются и пишут говно-код"

Не понял ничего. Какая проблема с this-то? То, что он ведет себя не так как в других ООП-языках? Так это стрелочными ф-ми решается. Или что-то другое?


Хотят везде pure-function, а где не получается, то хотя бы что-то издали похожее на pure-function

Ну "казаться а не быть" — это вообще проблема реакт-экосистемы. Везде какие-то нелепые рассуждения про ФП и чистоту, хотя по факту реакторедаксы — чистой воды процедурщина и никакого ФП с чистотой там рядом даже не пробегало.


В целом мало-мальски сложное приложение сейчас состоит из такого разнообразного бульона подходов. И render-methods, и контекст, и классовые компоненты (error-boundaries), и слоты, и хоки, и хуки.

А потом говорят про простой порог вхождения, ага. Он, может, и был простой — в 2015.
И главное-то что это бесполезная сложность — т.к. в данном случае знать надо не как делается Х, Y и Z (что расширяет возможности), а 100 разных способов сделать Х.

Пока писал ответ на меня снизошло озарение. Такое ощущение что экосистема React бодро так шагает к тому как писали PHP сайты 15 лет назад: помесь html, php, js, css & sql в одном файле. Ныне это JSX, JS || TS, cssInJS (и graphQL? :D).

Такое ощущение что экосистема React бодро так шагает к тому как писали PHP сайты 15 лет назад

https://en.wikipedia.org/wiki/XHP


С-но, да, "как в былые времена" — это основа реакта :)


Classes confuse both people and machines

Кек. Я не первый раз от команды реакта вижу это "confuse", оно нередко встречается в мотивации по всяким issues.
Но надо ли говорить, что у ребят какое-то свое странное мнение о том, что конфьюзит людей, а что — нет? :)


Conceptually, React components have always been closer to functions.

По-этому, чтобы не писать классы, давайте сделаем, чтобы эта функция от класса ничем не отличалась :)

Хуки — это способ использовать локальный стейт и вызывать сайд-эффекты (например запрос к API) в функциональных компонентах. До этого это было возможно только в компонентах-классах. В доках можно детали посмотре ь https://reactjs.org/docs/hooks-intro.html

Хуки — это способ использовать локальный стейт и вызывать сайд-эффекты (например запрос к API) в функциональных компонентах.

Так а зачем кому-то может захотеться использовать функциональный компонент, если в нем есть стейт? В этом и есть вопрос. Нафига это надо? Для чего? Какие проблемы в том, чтобы сделать компонент со стейтом классом?

Потому что это проще писать и меньше строчек кода. Если говорить про сайд-эффекты — useEffect — это ещё и безопаснее. В useEffect переданная функция будет вызван асинхронно в отличие от componentDidMount.

Потому что это проще писать и меньше строчек кода. Если говорить про сайд-эффекты — useEffect — это ещё и безопаснее.

Но это ведь просто не правда. Строчек кода столько же, "безопаснее" быть не может в силу полной эквивалентности семантики.


В useEffect переданная функция будет вызван асинхронно в отличие от componentDidMount.

В js любую синхронную ф-ю всегда можно вызвать асинхронно. А вот наоборот — нельзя. Так что синхронный интерфейс в подобных случаях более предпочтителен (тем более, что в 9 случаях из 10 хочется именно синхронной работы componentDidMount).

Но это ведь просто не правда. Строчек кода столько же, «безопаснее» быть не может в силу полной эквивалентности семантики.

строчек кода меньше.

В js любую синхронную ф-ю всегда можно вызвать асинхронно. А вот наоборот — нельзя.

в componentDidMount синхронный вызов будет откладывать отрисовку DOM. Иногда это правда надо, но из моего опыта как раз наоборот — 1 случай из 10.

но если нужен синхронный вызов то есть хук — useLayoutEffect
reactjs.org/docs/hooks-reference.html#uselayouteffect
строчек кода меньше.

Как меньше, если столько же? Они же 1к1 переводятся. Их не может быть меньше, по определению.


в componentDidMount синхронный вызов будет откладывать отрисовку DOM.

Так нам и не надо практически никогда рисовать дом, пока didmount не отработает. На самом деле, мне даже очень сложно представить случаи, когда нужно обратное поведение. Компонент ведь тогда находится в некорректном стейте, его by design нельзя рендерить в этом случае.


но если нужен синхронный вызов то есть хук — useLayoutEffect

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


В итоге та и остается непонятным, зачем кому-либо хотеть хоть в каком-то кейзе использовать хуки, если минусы — есть, а плюсов — никаких.

Sign up to leave a comment.

Articles