Pull to refresh

Comments 35

Я когда смотрю на реакт -- сам диву даюсь почему он выжил? Думаю, если бы не ресурсы Facebook и их психологи которые знают как и что впаривать, наверное он бы так долго не продержался. Например, его нетипичность и как следствие некоторый порог входа может использовать когнитивную ловушку страха потерь. Именно нетипичность, какая-то переусложненность, когда можно было иначе и проще. Если точнее -- ненаследуемость прошлого опыта, ломания его об колено, чистое навязывание React way вопреки прошлому "UX". Чтобы тяжесть соскока ощущалась пропорционально инвестированному времени.

Да потому что UI = f(x) это крутой подход. Куда уж проще-то?


Или вот подход к тому что все это компонент. Если помните, в ангуляре все пришли к тому что все делать через директивы. А react это упростил до "все компонент". и это круто.


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

как просто нытье жкверелюба

У вас все просто. Я зашел в реакт из Vue и мне есть с чем сравнивать.

С выходом React добрую половину конкурирующих фреймворков точно также по-быстрому сломали об колено и переделали на React-way. Начиная c AngularJS, у которого в 1.5 директивы неожиданно стали компонентами, при этом у них добавилось нормальное описание методов жизненного цикла, а контроллеры судя по документации стали бесполезны (они и до этого были, кстати, бесполезны, но не суть).

После выхода React все новые UI фреймворки начали переходить на однонаправленный поток данных, интерфейс как функция состояния. И это не только SPA-фреймворков касается. Мобильные фреймворки взяли от React нормальное описание интерфейса на языке программирования, а не через шаблонизатор (который по факту тоже язык программирования, но другой и плохой).

При этом упомянутые свойства React, это не какие-то его know-how. Они были по отдельности и до него. Описание интерфейса на самом языке программирования было например в Elm. Нормальное описание методов создание-изменения-удаление было например в D3.js. Но в React эти свойства кое-как совместили.

В итоге проекты, которые начали одновременно с первыми проектами на React писать на AngularJS или тем более на Jquery+Backbone, быстро стали неподдерживаемым куском говна. А проекты на React удавалось хоть и со скрипом, но поддерживать. Так React и выжил (это если отвечать на вопрос из вашего первого предложения). И по этой же причине под него стали косить другие фреймворки.

описание интерфейса на языке программирования
Но ведь JSX не является валидным JS, а лишь его надстройкой, которая во время компиляции сборки превращает XML-like конструкции в валидный JS-код — то есть это всё же не сам язык.

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

  • Оформление компонентов в классы

  • 3 метода жизненного цикла - componentWillMount (для SSR+client), componentDidMount (только client) и componentWillUnmount. Я бы предпочел, чтобы они более семантично и короче назывались, но это не большая проблема

  • Доступ к context (некоему глобальному объекту) из любого компонента без дополнительных импортов

  • Грамотно сделанный HTML-in-JS шаблонизатор со скоупом функции и JS-in-HTML

  • (иногда) Рефы, чтобы не генерировать уникальные идентификаторы для определенных частей компонента

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

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

Хуки вообще странный концепт, я с ними тоже не подружился. Ничего мне не нужно от того что они продают - а именно объединенный в один вызов useEffect маунт-размаунт и "переиспользуемость". Семантичные методы класса для жизненного цикла удобней и ssr поддерживают, а переиспользуемость легко и в классах реализуется. В остальном только проблемы от кода, превращающего в кашу из длинных грязных функций без явных слоев логики.

Обобрямс. У меня также есть глупые вопросы "сколько раз исполняется код" к функциональным компонентам (ответ -- на каждый рендер создаются новые замыкания. А потом разводим руками на вопрос, почему всё так тормозит). Переиспользуемость же реализует ООП. Да, в JS плохо с множественным наследованием, что вынуждает заниматься инкостыляцией, но жить можно.

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

Самое банальное -- разделить render на renderWait, renderReady, renderEmpty и renderError. Скорее всего, что-то из этого вам достаточно реализовать единожды.

Мне для моего пет-проекта для навигации в гетерогенной иерархической структуре требовалось реализовать несколько типов branch-node и leaf-node. Причём, естественно, поведение всех бранчей одинаково -- возможность дозапроса вложенных нод. Тут без множественного наследования вообще никак

У меня обычно в проектах разные интерфейсы для renderWait и renderEmpty, поэтому просто пишу get renderWait() { return <SomeMarkup /> } и в самом render() { if (isLoading) return this.renderWait; } . В целом тут только для очень специфических кейсов пригодится унификация и наследование, и если унифицировано - то лучше вынести на уровень выше, чтобы верхний компонент показывал соответствующую разметку, не раздувая нижние компоненты.

А разные типы одного компонента с общим функционалом сделал бы через class BranchWrapper{ render() { return Children.clone(this.props.children, { getChildNode: () => logic; }) } } . Так что варианты есть. Хотя это как раз React way, по которому не очень хочется идти, ООП довольно сильно усложняет восприятие, на мой взгляд. А еще лучше - через контекст, чтобы совсем отвязаться от пути Реакта - class SomeBranch { handleButtonClick = () => this.context.getNodes(this.props.branchId) }. Думаю, так проще, чем наследовать, но у каждого свой путь)

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

Если кому-то такой код

<script>
    let a = 1;
    let b = 2;
</script>

<input type="number" bind:value={a}>
<input type="number" bind:value={b}>

<p>{a} + {b} = {a + b}</p>

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

<script>
    let a;
</script>

<input type="number" bind:value={a}>
<p>{typeof a}</p>

И такой (я поменял type у поля ввода с number на date)

<script>
    let a;
</script>

<input type="date" bind:value={a}>
<p>{typeof a}</p>
Вы угадали!

number и string

Конечно, а чего вы ожидали? input типа date в value тоже строку хранит - это нативное поведение поля в браузерах, фреймворк тут не причем.

Тогда почему у первого number? У input любого типа value строку хранит. У меня не было вопросов если бы у обоих было string.

Да, действительно. Немного сахара, видимо, для чисел только

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

JSX был важнейшим нововведением. (я щщетаю). Все остальное холивар. Но да, теперь мы поуши в этом реакте.

Ну так в итоге-то что? Какие альтернативы нам использовать?

Альтернатив особо и нет. Только React + MobX + Typescript. И не надо упарываться по react way, реакт нужно использовать только как view слой, но никак не для управления состоянием. Управлять состоянием должен только MobX.

Vue, Svelte

Если противопоставить им голый React или React+Redux(или прочую схожую ерись), то да, реакт тут аутсайдер.

Но если им противопоставить React + MobX + Typescript и использовать реакт по назначению(то есть как библиотеку для рендера), то тогда все координально меняется. По сути ты получаешь все преимущества JSX'a и компонентного подхода, полноценную типизацию, настоящую реактивность(спасибо MobX) и не борешься с управлением состоянием приложения и отдельных компонентов, потому что этим занимается тот, кто должен, т.е. MobX.

В vue3 + pinia все хорошо с ts и типизацией. Да и "все преимущества jsx" для меня являются весьма противоречивыми. В любом случае vue в jsx умеет, а вот react в шаблоны vue - нет.

$mol

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

Я наблюдаю за развитием whatsup, как-будто глоток свежего воздуха, реактивность, производительность, нативность, минимализм api, jsx тоже есть и многое другое.

Классно написанная статья. Некий такой крик души )). Когда читаешь, начинаешь задумываться над темами вещами, что выделяет автор. Я думаю, что проблемы есть всегда и везде. Нет идеального инструмента, который бы удовлетворил разом всех заказчиков.

TL; DR: статья нытья, но почитать интересно

я не слишком близок к фронтенду, не слишком искушён в разработке, но я уверен, что претензии из раздела Ты слишком старый звучат в точности так же для проектов, не утруждающих себя обратной совместимостью: старые материалы неактуальны

React – это не универсальный молоток, круг его обязанностей очень узок: "react" отвечает за сравнение изменений между рендерами, "react-dom" – за то, чтобы внести эти изменения в DOM, JSX – за HTML-in-JS. Так как "react" требует писать компоненты чистыми, а это почти никогда невозможно на 100%, он также предоставляет хуки, чтобы обходить это ограничение.

Всё остальное – формы, менеджмент состояния и прочее – должно решаться сторонними библиотеками. Это очень сложно и не всегда получается хорошо, но примеры из статьи (типа сравнение форм в React и Svelte) просто притянуты за уши.

Автор, к сожалению, за 10 лет, так и не понял этого. Как и то, что useEffect не имеет прямого отношения к циклу жизни компонента.

Качество перевода, кстати, очень низкое. Как будто Google Translate читаешь.

Сам я разраб начинающий, поэтому всю статью обсуждать не возьмусь. Хочу только касательно Redux заметить: redux-tools очень облегчают жизнь, деля стейт на подразделы (слайсы). Внятность такого подхода вполне удовлетворительна, хотя есть и проблемы: горизонтальное взаимодействие между слайсами невозможно, они друг друга не видят в упор, что неудобно, когда надо загрузить соседнюю сущность в зависимости от загрузки первой.
С MobX не работал, не могу сравнивать. Это реально круче, чем redux-tools?

С MobX не работал, не могу сравнивать. Это реально круче, чем redux-tools?

Конечно, просто на порядки. Это небо и земля. Абсолютно другой подход и главное он по настоящему реактивный, а не в ручной подпиской. И куда просто самый минимум.


Вот ознакомьтесь - https://codesandbox.io/s/quirky-feynman-x3bzqr?file=/src/App.tsx

redux-tools очень облегчают жизнь
Вы про RTK?
есть и проблемы: горизонтальное взаимодействие между слайсами невозможно, они друг друга не видят в упор, что неудобно, когда надо загрузить соседнюю сущность в зависимости от загрузки первой.
А вы логику в редьюсерах держите? Попробуйте в thunk'ах.
Поскольку ты не видишь разницы между переменной и функцией
У автора проблемы с пониманием функций как объекта первого класса в JS? Какого поведения он ждёт, чтобы функции сравнивались как, через их вызов? Или чтобы функция считалась изменённой, если что-то в её скоупе/замыкании изменилось? А если там таймер по таймауту что-то внутреннее меняет, то тоже следить? А если функция делает куда-то запрос, результаты которого использует, то, может, ещё и запросы делать периодически, и если ответ поменялся, то перерисовывать компонент?
Потенциально эти эффекты могут запускаться слишком часто, что повредит производительности.
С чего бы им выполняться слишком часто? Там же список зависимостей вторым параметром, пока зависимости (в данном случае isVisible), не поменялись, функция выполняться не будет. Или вы тут время на «сравнить зависимости» экономите? А за что вы тогда там выше хвалили хуки, если вам так не нравится, как они работают?
Sign up to leave a comment.