Search
Write a publication
Pull to refresh

Comments 29

В React проектах реактивное программирование не всегда оправдано

Это пять!

React не реактивен. Так что все вроде логично

Всё-таки в нём есть модель реактивности, хоть и реализованная довольно криво из-за легаси. Но считать реактивным программированием исключительно RxJS, в котором не меньше проблем, точно нельзя.

На самом деле тут немного про разную реактивность.

Реактивное программирование — это парадигма, основанная на потоках данных (data streams) и распространении изменений

В React реактивность в реагировании и перестройке интерфейса при изменении состояния.

Так что если рассматривать React как сильно урезанную версию реактивного программирования, без явных потоков, императивно и с завязкой на компоненты, то можно притянуть. Но кажется этот спор немного бессмысленен.

Команда React сама официально декларирует что не хотела бы чтобы React удовлетворял принципам реактивного программирования https://ru.legacy.reactjs.org/docs/design-principles.html#scheduling

Это одна и та же реактивность, только на неё смотрят с разных позиций. Должна существовать возможность выражать потоки данных и автоматически распространять изменения. В React поток данных может быть выражен хуками useState, useEffect, useMemo и так далее, а распространение изменений производится в рендер-циклах на основе списков зависимостей. Не самая красивая и удобная реализация, но как есть. Реактивное программирование в общем случае не требует, чтобы данные были явно завёрнуты в некоторые объекты потока и чтобы ими можно было оперировать явно, это всё может быть скрыто под капотом как в Svelte (или даже Excel).

Все-таки useEffect вызывается после перерисовки компонента, а не непосредственно в ответ на изменение данных. Это связывает реактивность в React с жизненным циклом компонентов, а не с потоками данных, как в классическом реактивном программировании.

useEffect может банально не вызваться, если при перерисовке компонента произошла ошибка.

Да, потому что цикл обработки данных исторически был привязан к рендер-циклу. Поэтому сама реализация довольно убогая. С другой стороны, реактивность в React работает по pull-модели, когда данные втягиваются из потоков данных при необходимости, а не push-модели RxJS, когда они выталкиваются из потока. Но это не означает ущербность модели, просто в ней больше ленивости: просто нет смысла забирать и обрабатывать данные, если они не будут в конечном счёте отрендерены.

С этой позиции комментарий разработчиков React («Нам будет сложнее контролировать планирование, если мы позволим пользователям использовать подход «выталкивание при наличии данных», распространённый в функциональном реактивном программировании. Мы хотим, чтобы наш код был «связующим». В команде есть внутренняя шутка, что React должен был называться «Планировщик», потому что React не хочет быть полностью «реактивным».») следует понимать именно как следование pull-модели вычислений, а не когда события самостоятельно форсируют рендер.

Конечно, в более продвинутых реактивных реализациях, как у MobX, Vue, Solid, перевычисление зависимостей отвязано от рендер-цикла, и, соответственно, нет накладных расходов на непосредственно рендер виртуального DOM, но и они следуют pull-модели реактивности как более эффективной и даже более последовательной по духу функционального программирования.

Нет смысла забирать/обрабатывать данные, если в конечном итоге все данные идут в отрисовку. Но это не всегда так, не со всеми данными.

Я не говорил и не спорил про push и pull подход, и что это как-то влияет на отношение к функциональному реактивному программированию. По предложенной ссылке, команда React говорила частично про push подход, да, но больше про то, что вся логика там напрочь связана с тем что отрисовывается на экране.

React is not a generic data processing library. It is a library for building user interfaces.

If something is offscreen, we can delay any logic related to it. If data is arriving faster than the frame rate, we can coalesce and batch updates.

Думаю, именно поэтому ее и предложили в шутку назвать Schedule, а не из-за pull-based подхода.

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

Извините, но я всё же не понимаю, как это свидетельствует об отсутствии реактивности в React

Я не писал Вам по поводу отсутствия реактивности в React. Только о том что он не выполняет все принципы реактивного программирования, которое оперирует потоками данных.

А где, собственно, найти более-менее правдивый и полный список этих принципов? Разные сайты совершенно разные вещи пишут, а в документации Реакта принципы не перечислены.

Все верно. В зависимости от того, с кем вы общаетесь Frontend, Backend разработчком или архитектором, представление о реактивном программировании может немного отличаться.

Но кажется что обычно все сходятся на примерно этом свойстве.

The ability to describe a system like: a = b + c

And have that relationship represent a rule rather than an assignment. To ensure a always equals the sum of b and c were b or c to ever change. And that relationship never changes.

То есть зависимые данные должны обновляться автоматически и всегда.

Вот как раз всегда и автоматически React не удовлетворяет. И существенно ограничивает, где эти потоки можно определять ( только в рамках компонент).

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

Иногда надо сделать явно setState. Иногда - обновление вообще не произойдет.

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

Даже сами разработчики никогда не заявляли React как реактивное программирование. 

https://github.com/facebook/react/issues/14606#issuecomment-455259782

Вот цитата Dan Abramov, одного из ключевых фигур в React и Redux, про название React и отношение к Reactive programming.

«Yeah I don't think we have anything beyond Jordan considering rendering "reactive" to changing inputs. Even though it's not strictly reactive programming.»

В зависимости от того, с кем вы общаетесь Frontend, Backend разработчком или архитектором, представление о реактивном программировании может немного отличаться.

А ещё оно может различаться у разных людей, и, теоретически, об этом может зайти речь на собеседовании.

Вот как раз всегда и автоматически React не удовлетворяет.

Так если честно, то тогда только Svelte удовлетворяет этому правилу, потому что во всех остальных библиотеках реактивности придётся явно через них определять потоки и дёргать их геттеры/сеттеры/методы.

Иногда надо сделать явно setState

Это явно устаревшее и в функциональных компонентах недоступно.

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

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

Реактивность интерфейса это больше не про потоки данных, а про точечно изменение элемента. Если хотите настоящей реактивности, то стоит посмотреть на SolidJS и Vue, которые точечно меняют узел, а не перерисовывают дерево, за счет чего в них нет ререндера в принципе, со всеми вытекающими.

Нет, почему же: реактивность интерфейса — это способность интерфейса автоматически обновляться при изменении данных, на которые он опирается. Что же касается точечного изменения DOM, то он точечно меняется и в React, но через промежуточную отрисовку Virtual DOM. Но к реактивности это всё равно относится сильно косвенно.

Точечную отрисовку можно делать и без вдом, как например в preact. Вдом нужен был во времена экплорера, в котором дом работал медленно. Мы говорим про точечные изменения.

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

Точечную отрисовку можно делать и без вдом, как например в preact

Так ведь preact (и vue) используют VDOM.

Вдом нужен был во времена экплорера, в котором дом работал медленно.

VDOM реакту и подобным библиотекам нужен ещё и для композиции компонентов.

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

Это всё немного сложнее работает. Непосредственно рендер компонента порождает только vdom, а forceUpdate может инициировать реконсиляцию, но окончательно всё отрисуется только когда решит шедулер.

Ререндер наоборот указывет на отсутсвие реактивности

Если писать в таком стиле, что изменения данных не фиксируются явно в системе реактивности, и требуется постоянно делать forceUpdate, то да — это отсутствие реактивности. Но так писать очевидно неправильно. Тем более, что forceUpdate есть только у классовых компонентов.

Какая разница то, вызываешь ты форс апдейт или стейт меняешь - это в целом одно и то же.

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

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

Какая разница то, вызываешь ты форс апдейт или стейт меняешь - это в целом одно и то же.

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

Попробуйте SolidJs и увидете что такое реактивность

Вы плохо прочитали мои комментарии, иначе увидели бы, что я и его упоминал. А ещё задолго до него был KnockoutJS.

  • Сложные приложения (из наиболее известных — тот самый Netflix!)

Почему стримелка видеопотоков + поиск - это сложное приложение?

Ну как будто назвать Netflix простым, даже с точки зрения GUI, приложением - сильное упрощение.

Youtube же Вы наверное не считаете простым с точки зрения UI/UX взаимодействия приложением? Чем Netflix кардинально отличается?

Netflix - один из главных евангелистов RxJs. Начал использовать RxJs еще до Angular 2, как раз для решения проблем в реализации сложной бизнес логики.

Вообще это не так удивительно, учитывая java-бэкграунд Нетфликса, и то, что в те годы для JS практически никаких адекватных решений для реактивности не было.

От реката или рекативности? В чём минусы?

(вопрос от бэкендера)

В сравнении со многими другими фреймворками на текущий день довольно архаичен.

Виртуал дом не справился с задачами и проблемами, которые он собирался решить исходя из докладов еще в 2013г. Автоматическое обновление ДОМ и так далее, где якобы нам не нужно думать о перфомансе. По сей день это одни из основных вопросов при собесе на реакт стек.
Более того сейчас все кому не лень втянули signals. Что куда более простая концепция и весь этот виртуал дом не нужен, о чем писал автор svelte еще в 2018 году.
Ну и по мелочам, он менее удобен аналогов. Я с долей шутки, но и с большой долей реальности - реакт мертв и не лучший выбор для современного приложения.
Но на нем много написано, приходится еще использовать)

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

Спасибо!

А вообще индустрия уже разобралась какой должен быть идеальный гуй?

Почему спрашиваю: раз в году случается необходимость сделать что-то гуёвое (не важно веб или под десктоп или телефон). И каждый раз приходится смотреть что там в этой области понаизобретали.

Попробуйте solidjs, сейчас у многих боль в нижней части спигы от того, что не они придумали такую концепцию :)

Ну я из последнего, игрался с Alpine.js. Для стилей Tailwind.
Если надо SSR, то для аля 2010х Adonis.js + Edge.js, эдж это шаблонизатор из коробки. Но все на современный лад

Промежду делом: минусы примитивов продублированы. Список повторяется.

Sign up to leave a comment.