company_banner

Что нужно знать о популярных JS-фреймворках

    Привет! Меня зовут Дима Чудинов, я наставник на веб-факультете Яндекс.Практикума, Head of Group, Front-end, ABBYY.


    Студенты недавно задали мне вопрос: «Что лучше: Angular или React?». Я начал отвечать и понял, что мне понадобится для этого статья. Позже я понял, что и одной статьи не хватит.


    О том, какой фреймворк выбрать, я расскажу в другой раз. А в этой статье опишу историю создания фреймворков и их особенности. Выбрать рабочий инструмент статья не поможет. Зато поможет вести споры с другими разработчиками на кухне (если не будет карантина) и в сети. Статья будет полезна новичкам, которые только начинают своё знакомство с фреймворками и библиотеками, и поможет взглянуть на «зоопарк» веб-технологий сверху.



    Библиотеки и фреймворки


    Для начала важно понимать, что библиотека и фреймворк — не одно и то же.


    Библиотеки


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


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


    • jQuery — набор функций для манипуляций с DOM, работы с событиями и модуль для клиент-серверного взаимодействия.
    • D3 — библиотека для создания визуализаций с использованием SVG.
    • React — библиотека для отображения данных и управлению DOM деревом.

    Фреймворки


    Фреймворк — каркас приложения, который состоит из набора библиотек.


    Вместе они дают возможность пользователю выстроить свою функциональность на некотором фундаменте. Фреймворк задаёт структуру и подход к архитектуре вашего приложения, он диктует, как вы должны писать код. Например:


    • AngularJS — фреймворк для создания SPA, включает в себя инструменты для разработки и тестирования, реализует архитектуры MVC и MVVM, имеет открытый исходный код.
    • Vue.js — также фреймворк для создания SPA, реализует шаблон MVVM, имеет открытый исходный код.
    • Ember.js — ещё один фреймворк для создания SPA с открытым кодом, который реализует шаблон MVC.

    Что и когда используют


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


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


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


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


    Что было раньше


    React, Vue, lodash, D3… новичку порой сложно разобраться в этих названиях. Так в сети появилась шутка от разработчика, который всегда просит рекрутеров назвать, кто из стека в его профиле — покемон. Сможете отгадать?



    Интерпретация мема: "I typically ask recruiters to point out which of these are pokemon"


    Но у фронтендера не всегда было столько инструментов. В 2000-х годах не было понятия веб-приложений, существовали лишь сайты со статической разметкой, которую отдавали веб-сервера, написанные на PHP или .NET (C#). А вместо крутых анимированных кнопок на SVG были статические теги image.



    Google в 2000-е и сейчас. UX сильно отличается: изначально он был сделан на стандартных html-контролах, теперь это более сложные и стилизованные компоненты.


    Не было статей и вопросов в интернете на тему, какой фреймворк выбрать: «React, Angular или Vue?». Разработчики фокусировались на реализации функциональности и наполнении веба. Но были и пытливые умы, которые старались ускорить разработку и создавали библиотеки — с ними можно было писать меньше кода. Такие библиотеки давали возможность инженерам создавать более «богатые» приложения с динамикой, анимацией и прочими радостями, которые есть сейчас.


    Первые шаги к приложениям будущего


    В марте 2005 года появился Dojo Toolkit, который содержал виджеты, методы для работы с локальными хранилищами и REST-клиент. В июне 2006 года была выпущена альфа-версия библиотеки jQuery, которая включала в себя методы для манипуляций с DOM, работу с событиями, методы для анимаций и модуль AJAX. Все эти инструменты помогали унифицировать разработку, не писать одни и те же утилиты, шаблоны, а брать готовые протестированные модули.


    JavaScript: ES3 и ES5



    Javascript тогда заметно отличался от современной версии как по синтаксису, так и по возможностям. В 1999 году был опубликован стандарт ECMAScript 3. Он содержал хорошую базу той функциональности, что мы имеем сейчас. А вот стандарт ECMAScript 5 2009 года уже имел особенности:


    • расширенная работа со свойствами и атрибутами объектов, функциями (появился метод bind);
    • методы массивов, такие как filter, map, reduce;
    • сериализация и десериализация JSON;
    • вишенка на торте — strict mode.

    Переход к новому стандарту позволил сделать огромный шаг в развитии фронтенда, а именно Javascript. Как изменилось написание и объём кода можно увидеть на примере маленькой задачи:


    /**
     * Необходимо отфильтровать массив положительных чисел commonArray, 
     * чтобы в нём не осталось undefined
     */
    
    const commonArray = [1, undefined, 3, 6, undefined, 5, 2, undefined];
    let filteredArray = [];
    
    /**
     * Решение через for loop
     */
    for (let i = 0; i < commonArray.length; i++) {
      const item = commonArray[i];
    
      if (item !== undefined) {
        filteredArray.push(item);
      }
    }
    
    /**
     * Решение через Array.filter
     */
    filteredArray = commonArray.filter(function(item) {
      return item !== undefined;
    });
    
    /**
     * Решение через Array.filter в одну строчку (подходит для решения конкретно этой задачи)
     */
    filteredArray = commonArray.filter(Boolean);

    Куда делся ES4


    ECMAScript 4 был амбициозным проектом, но по слухам имел плохую совместимость с ES3. В итоге после долгих прений, техническим комитетом TC-39, в который входили участники из Google, Intel, Microsoft, Facebook, было принято решение продолжить работу над ECMAScript 3.1. Позже, в 2009, этот проект был переименован в ECMAScript 5.


    Эра фреймворков


    Новый стандарт дал огромный толчок развитию как Javascript, так и созданию новых фреймворков.


    Backbone.js


    В 2010 году появился Backbone.js — библиотека, которая реализует MPV (Model-Presenter-View) паттерн. С помощью Backbone.js можно было создавать SPA с клиентским рутингом. До этого клиентский рутинг был диким неукрощённым зверем, поэтому повсеместно использовали вариант с отдачей шаблонов — серверным рутингом.


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


    AngularJS


    В это же время произошёл релиз AngularJS от Google — полноценного фреймворка, который включал не только каркас приложений, но и средства для тестирования. Изначально этот фреймворк завоевал сердца разработчиков — на нём написано множество популярных сайтов. Например, сайт МакДональдса:



    Сайт МакДональдса, написанный на AngularJS


    Но несмотря на свою популярность, AngularJS сильно разочаровал разработчиков. Как так вышло — расскажу дальше.


    Ember.js


    2011 год принес Ember.js — ещё один SPA фреймворк со встроенным шаблонизатором Handlebars. Сам же фреймворк построен на классической архитектуре MVC (Model-View-Controller). У Ember очень дружное комьюнити, которое развивает инструмент и не останавливается, — даже в 2020 году у фреймворка есть роадмап и цели по развитию. Всё ещё можно встретить статьи: «Как мигрировать с React на Ember», поэтому этого старичка не стоит списывать со счетов.


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


    Хороший маркетинг — AngularJS


    В 2010 году разработчики Google выпустили фреймворк AngularJS. Поддержка крупной компании и хороший маркетинг сильно выделяли его среди равных — Backbone и Ember.


    Кроме этого, AngularJS предлагал на тот момент интересный подход — two-way data binding (с англ. двустороннее связывание данных), который ещё не был широко распространён в разработке.


    Особенности AngularJS


    AngularJS — полноценный фреймворк, целью которого было упростить разработку Single Page Applications.


    Основная особенность фреймворка в том, что отображение может менять модель, как и модель — менять отображение. Это нужно, чтобы связать действия пользователя. Например, пользователь вводит данные в поле → обновляется модель → посылается запрос на сервер → приходит ответ с сервера → обновляется модель → обновляется представление. Это и есть принцип two-way data binding.



    Схема взаимного обновления модели и представления


    Еще AngularJS привнёс несвойственный клиентским приложениям паттерн проектирования — Dependency Injection (с англ. внедрение зависимости).



    Упрощённая схема работы паттерна Dependency Injection


    Этот механизм позволяет легко подключать нужные зависимости модулям. Внедрение зависимости можно представить так: у вас есть команда, которая состоит из разработчика (контроллер), дизайнера (сервис) и контент-менеджера (константа). Все они сидят в одном кабинете (DI контейнер). Когда разработчику нужен макет, он обращается к дизайнеру, а тот берёт наполнение для макета у контент-менеджера. Это легко и быстро, ведь все они сидят в одном кабинете. На выходе разработчик получается всё необходимое для реализации проекта.


    Но AngualrJS не был бы фреймворком, если бы держался на паре паттернов. В него входит множество сопутствующих инструментов:


    • Animations — модуль анимаций;
    • Karma — тест-раннер при unit-тестировании;
    • Jasmine — фреймворк для unit-тестов;
    • Protractor — фреймворк для e2e тестов;
    • Поддержка локализации и интернационализации;
    • REST-клиент — модуль/библиотека для клиент-серверного взаимодействия (аналог fetch, XHR);
    • Router — библиотека, которая реализует работу с браузерной историей. Проще говоря, это переход по разным адресам внутри приложения.

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


    Недостатки


    AngularJS тянул с собой облегчённую версию JQuery — JQLite. Это было некоторым оверхедом для приложений, где JQuery был не нужен или у разработчиков была на него аллергия, для современных же приложений — совсем плохая практика.


    Но основная проблема была в “digest loop” и его производительности. Digest loop — то, на чём держится тот самый магический two-way data binding. Этот цикл работает так: при изменении модели запускаются все слушатели и происходит сравнивание текущих значений модели с предыдущими. Если функция слушателя изменяет модель, этот цикл будет повторяться до окончания сверки, то есть пока модель не перестанет меняться. Даже если функция слушателя ничего не поменяла, цикл запустит проверку минимум один раз, чтобы убедиться в консистентности модели.



    Принцип работы digest loop в AngularJS


    Тут и начинается проблема производительности из-за множественного запуска цикла и частых обновлений представления и модели. Это особенно ощутили разработчики, которые работали с “realtime data” или чьи приложения содержали большие и часто изменяемые модели.


    Проблему производительности так и не удалось исправить в AngularJS, ведь тогда пришлось бы переписать ядро и отказаться от обратной совместимости. Поэтому чуть позже появился Angular 2+ или просто Angular.


    Работа над ошибками — Angular 2


    В 2014 году в тёмных лабораториях Google неподалёку от зоны 51 (Area 51) начал создаваться новый фреймворк — Angular.


    В сентябре 2016 была опубликована первая версия финального релиза. После этого — анонс Angular 4, а 3 версия была пропущена. Это смутило разработчиков — все боялись повторения опыта AngularJS, связанного с поднятием мажорных версий и отсутствием обратной совместимости. Но, напротив, 4 версия была полностью совместима со 2.


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


    Особенности Angular


    Разработчики учли слабые места AngularJS. Изюминкой Angular 2 стал компонентный подход, которого не было в первом, добавилась изоморфность и, конечно же, — Typescript.


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


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


    Так выглядит небольшой компонент в Angular:


    @Component({
        /**
       * Тег, который будет можно использовать для вставки компонента навигации
       */ 
      selector:    'navigation',      
        /**
       *  HTML файл с разметкой
       */             
      templateUrl: './navigation.component.html',
        /**
       * Стили компонента
       */ 
      styleUrls:   './navigation.component.css'
    })
    
    /**
     * Класс для реализации логики поведения компонента и работы с другими сервисами
     */ 
    export class Navigation {
        /* . . . */
    }

    В Angular компоненты могут иметь собственное состояние, но если нужен глобальный state, то можно использовать сервисы и подключать их через Dependency Injection. Если поток данных более сложный и включает в себя много трансформаций, то, как правило, используют библиотеку NgRx.


    Ещё несколько новых возможностей Angular по сравнению с AngularJS:


    • Кроссплатформенность (PWA, Mobile, Desktop);
    • Code-splitting — разбивка кода на маленькие части, которые загружаются по мере работы с приложением;
    • Значительный рост производительности.

    Недостатки


    Typescript — не только особенность, но и недостаток Angular. Это отталкивает новичков, ведь писать без него Angular-приложения нельзя. Проблемы Typescript для обывателя: строгая типизация, ошибки, которые порой поправить очень сложно; разные концепты, такие как сложные типы, модификаторы доступа, дженерики, которые нужно понимать.


    Кроме этого, Angular — фреймворк с богатыми возможностями, на изучение которых требуется время, нет, скорее, много времени. Поэтому иногда новички сдаются и переходят на более «лёгкие» фреймворки. Но те, кто упорно продолжает осваивать Angular, — редко в нём разочаровываются.


    Серебряная пуля от Facebook — React


    В 2011 году команда Facebook проводила эксперименты по созданию фреймворков, которые решали бы проблему производительности, а именно — каскадных обновлений. Существовавшие на тот момент решения — AngularJS, Backbone, Ember, Knockout — не давали нужного результата.


    У Facebook появилось прототипное решение — FaxJS. Этот проект имел свои особенности:


    • Изоморфность;
    • Компонентный подход;
    • Реактивность — отображение изменялось в соответствии с изменением состояния компонента;
    • Быстрота работы в контексте рендеринга.

    Изначально на FaxJS построили Facebook Ads Org, а затем Instagram испытал его на своей ленте. Проект FaxJS был экспериментальным и дал начало знаменитому сегодня React. В 2013 React был уже представлен как open-source библиотека на JSConf US.


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


    Особенности React


    Virtual DOM, или виртуальный DOM, — легковесная копия реального HTML DOM в виде JS-объекта в памяти, с которой работает приложение. Он агрегирует в себе все динамические изменения, а уже после применяет их к реальному DOM.


    Основная проблема нативного HTML DOM — его скорость при работе с динамическими данными: из него дорого как читать, так и много и часто писать. Виртуальный DOM не является простым объектом, который хранит данные, он имеет эффективные и производительные алгоритмы для сравнения и группировки изменений и выборочных изменений отдельных частей HTML DOM.


    Небольшое DOM-дерево:


    <div class="container">
        <p>Some simple text</p>
    </div>

    Упрощённый пример виртуального DOM:


    const virtualDOM = {
        tagName: "div",
        attributes: { "class": "container" },
        children: [
            {
                tagName: "p",
                textContent: "Some simple text"
            }
        ]
    }
    

    Другой новый концепт, который привнёс React, — JSX (Javascript and XML). Это синтаксический сахар или, по-другому, расширение JavaScript. JSX напоминает язык шаблонов, наделённый силой JavaScript.


    JSX разметка:


    <div className="container">Content</div>

    Результат превращения в JS:


    React.createElement("div", {
      className: "container"
    }, "Content");

    Мы уже говорили про архитектурные паттерны MVC и MVVM, так вот React и его компоненты — это буква “V” в MVC/MVVM, то есть view или представление. Такой подход позволяет писать переиспользуемые компоненты и собирать большие функциональные блоки с помощью композиции более мелких компонентов. Так можно описать форму, которая состоит из разных атомарных компонентов на JSX:


    <FormComponent>
        <InputComponent type="text" name="userName" onChange={handleChange} value={userName} />
        <InputComponent type="password" name="password" onChange={handleChange} value={password} />
        <ButtonComponent type="submit">Click me</ButtonComponent>
    </FormComponent>

    С помощью такого компонентного подхода и композиции можно формировать представления любой сложности.


    Недостатки


    React — слой представления, который не имеет никаких моделей. Иначе говоря, в нём негде хранить данные. Более того, их практически нельзя переиспользовать между компонентами, ведь передача свойств из компонента в компонент на несколько уровней ведёт к антипаттерну — prop drilling.


    Проблема такого поведения в том, что при изменении этих данных — добавлении или удалении свойства — требуется пройтись по всем компонентам, где происходит передача, и сделать исправления. Кроме этого, сами свойства могут изменяться (новое имя или информация). В любом случае подход prop-drilling тратит много ресурсов разработчиков и ведёт к появлению багов.



    Схема передачи свойств через множество уровней компонентов, что приводит к prop-drilling


    Разработчики Facebook понимали эту проблему и добавили в экосистему React новый инструмент — Flux.


    Попытка уложить всё по полочкам — Flux


    Flux — не только библиотека для хранения глобального состояния приложения, но и архитектурный паттерн. Этот инструмент в первую очередь был представлен в дополнение к React, хотя сама архитектура может применяться где угодно, иначе говоря, framework-agnostic.


    Особенности


    Схема передачи данных между компонентами в React, как и у любого приложения, которое использует подход MVVM, выглядит так:



    Обычная схема взаимодействия многих MVVM-фреймворков


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


    Flux состоит из 4-х главных частей:


    • Dispatcher — диспетчер или объект, который получает действия и направляет их в хранилища. Диспетчер единственный на все приложение.
    • Store — хранилище для данных. Оно реагирует на действие, которое направляет диспетчер, а затем отправляет событие на своё изменение.
    • Actions — действия или простые объекты, которые могут отправлять представления для обработки центральным диспетчером.
    • Views — знакомые уже представления, в наиболее частом случае это React-компоненты.

    Так выглядит однонаправленный поток:



    Схема движения данных во Flux-архитектуре


    «Представление» отправляет некоторое действие, которое попадает в «Централизованный диспетчер». Он в свою очередь оповещает все «Хранилища», которые в нём зарегистрированы. «Хранилища» обновляют модель и оповещают об изменениях «Представления». Такой круговорот происходит постоянно, пока мы не закроем приложение, ну или оно не упадёт в белый экран, например с ошибкой “Uncaught (in promise) Error: ...”


    Недостатки


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


    Поэтому в 2015 году Даниил Абрамов и Эндрю Кларк представили комьюнити новый инструмент — Redux. Он реализует Flux-архитектуру, но при этом имеет некоторые преимущества.


    На этот раз получилось лучше — Redux


    Redux — библиотека с простым API, хранилищем состояния приложения, или state container с однонаправленным потоком данных. Во Flux содержится множество хранилищ, в Redux — одно глобальное.


    Особенности


    Поток данных в React с Redux и без него имеет огромные отличия. Представьте, что вы продаёте значки: самостоятельно ищете точки сбыта через знакомых, что может быть сложно и неэффективно. Так работает React без Redux. Но стоит добавить Redux, как появляется большая площадка для сбыта — Redux store. Это можно сравнить с Wildberries или Lamoda, куда продавец выставляет товар и не тратит время на продажу самостоятельно. Так это выглядит на схеме:



    Сравнение передачи данных в React с использованием Redux и без него


    Схема потока данных в Redux:



    Схема движения данных в Redux


    Вам уже знакомы почти все элементы, кроме Reducer.


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


    Несмотря на то, что Redux был создан с фокусом на React, он вполне нашёл себе применение с другими библиотеками и фреймворками, даже с AngularJS.


    Недостатки Redux


    Redux немного удручает большим количеством бойлерплейта (кода, который нужно писать, хотя он не несёт в себе логики): на каждую команду нужно написать Action (иногда асинхронный), Reducer, Selector. Чем больше кода пишешь, тем больше бандл.


    Комьюнити позиционирует Redux простым инструментом, но с ним всё равно нужно «набить руку»: изучить тонкости и способы применения, научиться проектировать хранилище, а это, как правило, не всегда получается с первого раза.


    На связке React и Redux пишут много проектов, поэтому Redux популярен и в 2020 году. Это не самая простая библиотека, а правильное её применение требует знаний и опыта.


    От Multipage к SPA и обратно — Next.js


    До этого я рассказывал про SPA-фреймворки, которые динамически могут строить страницы без перезагрузки. SPA-приложения обычно включают в себя много кода, который нужно получить при первом старте приложения. Это бьёт по быстродействию открытия страницы и конечно же влияет на UX (с англ. User Experience). Кроме этого, поисковые боты не особо расположены индексировать страницы, построенные на JS, — в 2020 году Google-Bot один из немногих, кто индексирует SPA.



    Влияние скорости загрузки страницы на настроение пользователя


    До новомодных SPA в тренде был подход multipage, который не имел таких проблем. При этом, чтобы отобразить новое состояние страницы, её нужно было перезагрузить.


    Объединить две стратегии работы с приложением взялась компания ZEIT. Так в 2016 году был выпущен SSR (Server Side Rendering) фреймворк — Next.js. Он работает поверх React и позволяет быстро писать и разворачивать multipage приложения, а после получения страницы — работать как с полноценным SPA.


    Особенности


    Главная особенность Next.js — SSR. Этот фреймворк построен поверх React, поэтому вовсю использует его изоморфность, что позволяет отдавать шаблоны с преднаполненными данными. После этого на страницу добавляется скрипт, который не блокирует построение DOM, и впоследствии загружает весь необходимый JS для динамической работы со страницей. После отображения данных, пользователь взаимодействует со страницей как с полноценным SPA-приложением.


    Сode-splitting (с англ. разбивка кода) — ещё одна важная особенность, которая позволяет ускорить открытие отдельных страниц. При получении отдельной странички мы передаём в качестве JS-кода не всё приложение, а лишь малую его часть. Поэтому передача данных по сети происходит быстрее — браузер выполняет код и не тянет лишние зависимости, которые не будут использоваться на нужной странице.


    С Next.js можно колоссально сэкономить время на развёртывание приложения — достаточно одной команды. Кроме этого, он берёт на себя всю чёрную работу, которая не всегда приносит удовольствие.


    У него есть ещё пара особенностей:


    • Поддержка Typescript;
    • Hot Reload — сразу видны изменения на странице;
    • Встроенный Router.

    Недостатки


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


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


    Кроме этого, Next.js — большой проект, в который придётся вникать, хотя документация и комьюнити весьма хороши.


    В 2015–2016 годах было много холиваров на тему SPA vs SSR. Всё новое — хорошо забытое старое, поэтому разработчики с удовольствием встретили multipage-подход, предложенный Next.js. Тем не менее SPA приложения ничуть не потеряли популярность, а, наоборот, стали дополнять SSR. В 2020 году прекрасно применяется как SPA-, так и SSR-подход — каждый из них решает свои задачи и подходит для определённых типов приложений, а количество холиваров на эту тему заметно уменьшилось.


    Из Китая с любовью — Vue.js


    В 2014 году React только набирал обороты, AngularJS, наоборот, утрачивал свою популярность, а Angular находился ещё в стадии активной разработки. У фронтенд-разработчика уже был большой выбор инструментов, но не все проблемы фреймворков и библиотек были разрешены. Например, сохранялись такие проблемы, как высокий порог входа, низкая скорость разработки и необходимость писать большое количество кода, чтобы приложение «взлетело». Для решения этих проблем появился новый фреймворк — Vue.js. Его создатель, бывший сотрудник Google, активно использовал AngularJS в своей работе, поэтому Vue.js синтаксически на него похож.


    У Vue.js был долгий путь становления — фичи добавлялись от релиза к релизу. В начале многие предсказывали ему провал, но с выходом новых версий он только набирал популярность: последняя версия 3.0 вышла в 2020 году. В развитии ему помогло сплочённое азиатское комьюнити разработчиков, а в популяризации — евангелисты.


    Довольно быстро фреймворк вошёл в топ-3 китов и стал тягаться с Angular и React:



    Сравнение статистики топ-3 фреймворков на Github


    Особенности


    Vue позаимствовал лучшие практики из разных инструментов.


    Cинтетический пример использования шаблонов:


    <!-- v-if, как и ng-if определяют необходимость отрисовки элемента на странице -->
    
    <!-- Vue.js -->
    <span v-if="disabled">{{ message }}</span>
    
    <!-- AngularJS -->
    <span ng-if="disabled">{{ message }}</span>

    Пользователям понравилось в этом фреймворке многое: от низкого порога входа до скорости разработки приложений.


    Из особенностей Vue.js выделяют:


    • Two-way data binding (подобно Angular);
    • SSR, как коробочное решение есть Nuxt.js;
    • Компонентный подход (компоненты имеют свой жизненный цикл, что схоже с концепцией React);
    • State container — Vuex (аналог Redux для React);
    • CLI — command line interface, или набор утилит для разработки приложений;
    • Возможность использовать JSX для написания компонентов;
    • Малый размер при сборке в сравнении с React и Angular.

    Vue не привнёс что-то новое, он взял уже наработанный багаж знаний из React/AngularJS/Angular и других инструментов, убрал раздутое и сложное API и привёл всё к минималистическому виду.


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


    Недостатки


    На протяжении становления и развития этого фреймворка разработчики жаловались на небольшое комьюнити и отсутствие гайдов по написанию масштабных приложений. При достижении определённого LOC (lines of code — количество строк кода) и сложной бизнес-логики они не знали, куда и как двигаться дальше. При этом приложение начинало дублировать код и терять унификацию.


    Хорошая новость: комьюнити выросло и появился неплохой опыт разработки на Vue.js, поэтому эти проблемы практически себя изжили.


    Другой недостаток — компонентный подход не дотягивает до конкурентов вроде React по гибкости. Но в этом нет вины Vue.js, ведь это фреймворк, который предоставляет инструменты для полного цикла разработки приложения. Тогда как React — библиотека для рендеринга, которая в основном фокусируется на компонентном подходе.


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


    Черная магия — Svelte


    Казалось бы, топ-3 лидеров продакшена очевиден и устоялся, но комьюнити этих инструментов было недостаточно. Им нужен был быстрый и простой фреймворк, который виртуозно решает повседневные задачи, имеет всё из коробки, и его результирующий код не занимает много места. Последним не могут похвастаться ни React, ни Angular, ни Vue.


    Svelte впервые презентовали сообществу в 2016 году, но первая версия особо не продвигалась. Популяризация фреймворка началась со второй версии в 2018 году, а с выходом третьей версии о нём наконец заговорили в комьюнити.


    Особенности


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



    Как работают Svelte и React под капотом


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


    Фреймворк/библиотека Размер, кб
    React (v.16) 97.5
    Vue (v.2) 58.8
    Angular (v.2) 566
    Svelte 0

    Со временем цифры уменьшаются, но у Svelte по-прежнему остаётся 0.


    Кроме этого, Svelte может похвастаться:


    • Высокой производительностью в “runtime” (во время выполнения кода, например в браузере);
    • Библиотекой анимаций из коробки;
    • Изолированной работой со стилями;
    • Поддержкой SSR;
    • Кроссплатформенностью (Svelte Native);
    • Поддержкой Typescript.

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


    Недостатки


    Бедный CLI или, точнее, отсутствие официального поддерживаемого CLI для Svelte — ощутимый недостаток. Ведь генерация каркаса и сборка возможна только с помощью сторонних шаблонов для развёртывания проекта.


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


    Ещё один недостаток — небольшое комьюнити. Этот вывод можно сделать по количеству вопросов на https://stackoverflow.com/, где их заметно меньше, чем у Angular или Vue.


    Фреймворк Svelte не поддерживается корпорациями, а продвигается за счёт комьюнити. Несмотря на отсутствие больших вложений в маркетинг, Svelte обзавёлся 40k stars на github. Его часто обсуждают на профессиональных конференциях и в блогах, что говорит о его потенциале.


    Заключение


    В 2020 году лидерами среди фреймворков и библиотек по-прежнему остаются React, Angular и Vue.


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


    Если вам захочется освежить в памяти все рассмотренные фреймворки и библиотеки из этой статьи, просмотрите таблицу:


    Название Год появления Особенности Недостатки
    AngularJS 2010 В основе лежит паттерн Dependency injection.
    Использует Two-way data binding подход.
    Встроенный Router.
    Встроенная библиотека анимаций.
    Наличие тест-раннера.
    Встроенный HTTP-клиент.
    Обязывает использовать JQuery.
    Имеет проблемы производительности.
    Angular 2016 Позволяет писать SSR приложения.
    В наличии богатый CLI.
    Кроссплатформенный.
    В основе лежит паттерн Dependency injection.
    Использует Two-way data binding подход.
    Имеет встроенный Router; Своя библиотека для анимаций.
    Наличие тест-раннера.
    Встроенный HTTP-клиент.
    Интернационализация.
    Code-splitting.
    Написан на Typescript.
    Высокий порог входа.
    Большой размер бандла.
    Обязательное использование Typescript.
    React.js 2013 Высокая производительность рендеринга.
    Позволяет писать изоморфные приложения.
    Использует компонентный подход.
    Реактивность.
    Концепция Virtual DOM.
    Компоненты пишутся с использованием JSX.
    Поддержка Typescript.
    Работает только с отображением, не предназначен для работы с данными.
    Flux 2014 Предсказуемый поток данных.
    Легковесная библиотека.
    Поддержка Typescript.
    Высокий порог входа. Отсутствие гибкости в переиспользовании кода.
    Redux 2015 Ещё более предсказуемый поток данных, чем во Flux.
    Легковесная библиотека.
    Поддержка Typescript.
    Не самый низкий порог входа.
    Необходимость писать много бойлерплейта.
    Next.js 2016 SSR-фреймворк.
    Code-splitting из коробки.
    Поддержка Typescript.
    Хороший CLI, который не требует настройки для запуска приложения.
    Встроенный Router.
    Hot reload из коробки.
    Жёсткая структура проекта.
    Негибкая конфигурация сборки.
    Vue.js 2014 Низкий порог входа.
    Two-way data binding.
    Изоморфный фреймворк.
    Неплохой CLI.
    Компонентный подход.
    Возможность использовать JSX.
    Поддержка Typescript.
    Не такое большое комьюнити, как, например, у React.
    Слишком большая гибкость, которая может привести к архитектурным проблемам.
    Svelte 2016 Не занимает место в результирующем бандле.
    Высокая производительность.
    Встроенная библиотека анимаций.
    Поддержка SSR.
    Кросплатформенный.
    Поддержка Typescript.
    Небольшое комьюнити.
    Слабый CLI.
    Небогатая экосистема.

    Полезная литература


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


    AngularJS и Angular


    https://github.com/toddmotto/angularjs-styleguide — стайл-гайд по AngularJS с примерами кода.


    https://github.com/PatrickJS/awesome-angular — подборка инструментов для полноценной работы с Angular и изучения экосистемы.


    React.js


    https://github.com/enaqx/awesome-react — подборка инструментов для полноценной работы с React.js и изучения экосистемы.


    https://pomb.us/build-your-own-react/ — туториал о том, как написать свой React.js.


    Redux


    https://redux.js.org/introduction/getting-started — первое, что нужно посетить при знакомстве с Redux.


    Next.js


    https://github.com/unicodeveloper/awesome-nextjs — подборка инструментов для полноценной работы с Next.js и изучения экосистемы.


    Vue.js


    https://github.com/vuejs/awesome-vue — подборка инструментов для полноценной работы с Vue.js и изучения экосистемы.


    https://nuxtjs.org — альтернатива Next.js при работе с Vue.js.


    Svelte


    https://svelte-community.netlify.app — огромная подборка инструментов и новостей от комьюнити.


    Интересно


    https://github.com/tastejs/todomvc — примеры небольших приложений to-do листов, реализованных на разных инструментах.


    https://github.com/gothinkster/realworld — примеры приложений на популярном стеке, которые можно разобрать, чтобы понимать, как это пишется в реальной жизни.

    Яндекс.Практикум
    Помогаем людям расти

    Comments 97

      +1

      А кроме js других фреймворков нет

        +3
        Я как понял речь про название, поправил, спасибо
        +2
        Для уменьшения бойлерплейта и упрощения Redux существует redux-toolkit с концепцией слайсеров и redux-thunk из коробки.
          +2
          Все верно, но это не отменяет наличие бойлерплейта в Redux из коробки. Но тулкит — это еще одна библиотека поверх redux (как раз в конце дана ссылка на getting started в секции redux, где говорится о тулките), без которой сейчас действительно нет смысла писать redux приложения, если нет какой-то своей инфраструктуры или оберток.
            +5
            Как ни крути это как было Г, так таковым и осталось.
              +2
              «Есть всего два типа языков программирования: те, на которые люди всё время ругаются, и те, которые никто не использует.»
              Bjarne Stroustrup.

              То же можно сказать и о библиотеках.
                0

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


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


                Поэтому нет, "то же самое" о библиотеках сказать нельзя.

              0
              когда не было async/await я понимал зачем люди используют thunk, а вот сейчас я не понимаю.
                0
                Потому что удобно? Можно, конечно, импортировать getState и dispatch из redux, после чего дергать из обычных функций, но почему бы не пойти по рекомендованному пути middleware?
                  0
                  Потому что удобно? Можно, конечно, импортировать getState и dispatch из redux, после чего дергать из обычных функций, но почему бы не пойти по рекомендованному пути middleware?

                  Удобно использовать Redux? — Смешно.
                  Удобно использовать redux-thunk? — Смешно в квадрате.

                  Уже практически 2021 год на дворе, а вы застряли в 2014 году.

                  но почему бы не пойти по рекомендованному пути middleware?

                  Вот так и рождается говнопроекты, думать головой не хотим, просто смотрим как написано в примере и как рекомендуют «умные авторы». Ну раз так написано или так рекомендуют это ведь не говнокод да? Ага, обязательно.
                    +2
                    Удобно использовать Redux? — Смешно.
                    Удобно использовать redux-thunk? — Смешно в квадрате.

                    Поумерьте свой пыл. Говоря о целесообразности использования redux-thunk, мы предполагаем что redux уже есть в стеке. И да, я считаю что в правильных руках redux может быть удобен. Предвосхищая вопросы — mobx я пробовал, не понравилось.

                    Вот так и рождается говнопроекты, думать головой не хотим, просто смотрим как написано в примере и как рекомендуют «умные авторы».

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

                      Всё кроме "однодневок" из этого — всецело применимо к редаксу, если что. Ну да и MobX совсем не однодневка.


                      Зато сделали не как в скучных примерах из документации.

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

                        0
                        Можете пояснить, в каком месте концепция middleware вообще и redux-thunk в частности — это натягивание совы на глобус?

                        На мой взгляд, это как раз грамотное разделение кода по слоям для уменьшения связности. Есть компонент:

                        const MyComponent = ({data, onUpdateData}) => (
                           ...
                        );
                        


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

                        connect(state => {
                           data: state.data
                        }, {
                           onUpdateData: updateData
                        })(MyComponent )
                        


                        Если updateData — просто меняет состояние, делаем обычный экшн. Если нужен асинхронный код, описываем thunk-овский экшн:

                        const updateData = data => dispatch => {
                          ...
                        };
                        


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

                        На мой взгляд, это весьма удобно.
                          0
                          Можете пояснить, в каком месте концепция middleware вообще и redux-thunk в частности — это натягивание совы на глобус?

                          С концепцией middleware всё хорошо. Применение этой концепции там, где она слишком многословна, раздута, или же вообще полностью не нужна — вот это и есть "натягивание". Когда у тебя в руках редакс, все проблемы становятся похожи на редьюсеры, экшены, и мидлвари, ага.


                          Если вы хотите поговорить про натягивание совы — давайте поговорим, например, о том, как редакс предлагает работать с концепцией события. То есть каким-то единичным моментом, который случился в одной части вашего приложения, и который надо как-то обработать в другой его части.


                          В итоге у нас очень низкая связность.

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


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

                          вы совершенно не сможете обеспечить. Стоит вам только выкинуть редакс, как вам придётся
                          а) переделать все импорты компонентов с "приконнекченых" на простые, не прошедшие через connect();
                          б) самое главное — обеспечить проброс данных и коллбеков в компоненты, которого у вас без редакса просто вообще не будет.


                          Вы, конечно, можете сказать, что пункт б — это и есть редакс, и выкинув его, логично, что останется дыра на этом месте. Но беда в том, что эту дыру можно заткнуть только чем-то архитектурно крайне похожим на редакс, и ничем другим. Её не заткнуть (без долгого дописывания кода) ни FRP-либами, ни собственными механизмами реакта, ни кучей других вещей. Только каким-то API, очень похожим на connect().
                          Так какая же тут низкая связность?

                            0
                            С концепцией middleware всё хорошо. Применение этой концепции там, где она слишком многословна, раздута, или же вообще полностью не нужна — вот это и есть «натягивание».

                            Замените слово middleware на любое другое — и ваше утверждение останется верным. Любая концепция хороша, когда совпадает с ожиданием и плоха, когда задачи приходится адаптировать под нее.

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

                            Эм… Никак?) Редакс управляет состоянием, отслеживание событий — это уже не к нему.

                            Если она вам нужна — это прекрасно. Если нет — вы написали гору разнесенного по разным частям приложения кода ни для чего.

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

                            Только каким-то API, очень похожим на connect().

                            Например, любым HOC.
                              0
                              Любая концепция хороша, когда совпадает с ожиданием и плоха, когда задачи приходится адаптировать под нее.

                              Именно так. Это ровно то, что я вам написал два коммента назад.


                              Эм… Никак?) Редакс управляет состоянием, отслеживание событий — это уже не к нему.

                              Редакс рекламирует себя как средство избавления от props hell. Что значит "не к нему"? Сделать это (вызов кода в одной части приложения от каких-то факторов в другой) на голом реакте — это как раз props hell (или контексты, с которыми тоже масса проблем), что редакс предлагает по этой проблеме, если уж он устраняет props hell?


                              Например, любым HOC.

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

                                0
                                Я не особо интересовался, как именно себя рекламирует редакс. Я знаю, какие задачи он реально решает. И это — управление глобальным состоянием и точка. Если вы будете пытаться его применить не для того, для чего он предназначен — ожидаемо ничего хорошего не выйдет.

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

                                const events = createSlice({
                                   name: 'events',
                                   initialState: {
                                      myEvent: null
                                   },
                                   reducers: {
                                      sendMyEvent: (state, {payload}) => {
                                         state.myEvent = payload;
                                      }
                                   }
                                });
                                


                                Далее компоненты коннектят нужное событие, подписываясь на него и ставят в зависимость в useEffect, если надо.

                                Покажите, как вы начнете писать HOC, который передаст в компонент какие-то произвольные, нужные конкретному экземпляру компонента данные и коллбэки.
                                Или вы на каждый в-прошлом-редаксовский компонент пойдете писать свой HOC? Отлично. Или не совсем «свой», а связывающий некие поля в некоем хранилище с пропсами? Ну тогда вы свой редакс так напишете.

                                Ну, в какой-нибудь mobx это будет inject и observer.

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

                                Вообще, изначально разговор шел об redux-thunk. Вопрос стоял, как я понял, зачем его использовать, если можно прям из коллбэков вызывать dispatch, импортируя его из redux. И тут ответ — потому что таким образом мы или нагружаем компонент логикой или, по крайней мере, обязываем разбираться в специфике обработки коллбэков. Что повышает связность.
                                  +1
                                  Вот поэтому и тянет махнуть рукой на React и уйти в Angular.

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

                                  Вот, допустим, история пет-проекта за которую мне стыдно — объявил нуб configureStore примерно как:
                                  export const store = configureStore({
                                    reducer: {
                                      auth: authReducer,
                                      weather: weatherReducer
                                    },
                                  })
                                  и решил использовать axios (при работе с каждым слайсом при обращении к серверу будет использован токен, хранящийся в слайсе auth).

                                  Пока реализую логику следующего вида в react-компонентах
                                  axios.post(...)
                                  .then(...)
                                  .catch(..)
                                  
                                  все нормально, потом в воспаленном сознании возникает идея куда-то вынести эту логику (она же, как ни странно будет использоваться повторно), и тут выясняется что пользовательские хуки вроде
                                  export const useWeather = () => {
                                      const dispatch = useDispatch()
                                      const connection = useSelector((state: State) => state.auth.request)
                                      const updateWeather = useCallback(() => {
                                          connection.post('/weather/update')
                                              .then((res: any) => {
                                                  console.log(res.data[0].name)
                                                  dispatch(update(res.data[0]))
                                              })
                                              .catch((err: any) => console.log(err.response.data.message))
                                      },[])
                                      return { updateWeather }
                                  }
                                  помочь не могут, так как (внезапно!) хуки просто так не работают с асинхронным аксиосом (Error: Actions must be plain objects. Use custom middleware for async actions).

                                  Ищу себе как разрулить ситуацию и тут на тебе — из Вашей с JustDont переписки понимаю, что я то ли отстал на много лет то ли изобретаю ненужный велосипед и даже непонятно нужно ли искать описание конструкций вроде
                                   const updateData = data => dispatch => {
                                    ...
                                  };.
                                  на redux-toolkit.js.org или где-то еще.

                                  Но главное — непонятно сколько еще, при такой свободе, ошибок в архитектуре я допущу. То есть React то крут и здорово что есть гибкость, но как в нем не ошибиться новичкам — непонятно.

                                  Есть, конечно, авторы навроде Владилена Минина, но как-только нужны дополнительные возможности, думаешь «тут в MERN только Redux добавлю и все», а оказывается шаг в сторону от готовых примеров архитектуры — потенциальные велосипеды и грабли, так как нет одной единственно актуальной модели.
                                  Если что, позор находится по адресу github.com/pilot87/Forecast_Trading
                                    +1
                                    Вокруг реакта есть куча старых и новых надстроек и библиотек и какие в каком виде применять для меня как для новичка во фронтенде — загадка

                                    Увы, это так( Сложность освоения часто обратная сторона гибкости.

                                    непонятно нужно ли искать описание конструкций вроде <...> на redux-toolkit.js.org или где-то еще.

                                    Это redux-thunk. Просто в тулките он идет из коробки.

                                    На мой взгляд, именно в thunk-овских action-ах надо концентрировать бизнес-логику, работу с АПИ и т.д. А из компонентов только их вызывать.

                                    Вообще, складывается ощущение что будет не лишним запилить пост, где описать собственный опыт работы с redux.
                                      +1
                                      Спасибо за направление, а пост почитаю с удовольствием — фронтенд тот еще темный лес, да и Вашему аккаунту статья пойдет на пользу
                            0
                            Если updateData — просто меняет состояние, делаем обычный экшн. Если нужен асинхронный код, описываем thunk-овский экшн:

                            А зачем, если можно просто написать
                            const result = await getSomeData();
                            store.dispatch(someDataUpdated(result));
                            ?


                            Ну или просто
                            const result = await getSomeData();
                            someDataUpdated(result);


                            и забыть вообще, что где-то рядом есть какой-то редакс.


                            JustDont


                            Если вы хотите поговорить про натягивание совы — давайте поговорим, например, о том, как редакс предлагает работать с концепцией события.

                            Проблема как раз в том, что на практике — никак не предполагает. В 99% проектов action = function, а не action = event.

                              0
                              Проблема как раз в том, что на практике — никак не предполагает. В 99% проектов action = function, а не action = event.

                              Дык не в этом проблема. Проблема в том, что с одним только action (чем бы оно не было) редакс не редаксится. "В теории" надо в стор писать, чтоб сам механизм редакса работал. На практике сделал у нас как-то один очень мудрый программист синхронизацию скролла двух окошек через редакс. Тут-то он и узнал, как можно поставить на колени довольно производительный компьютер одной только обработкой скролла.

                                0
                                "В теории" надо в стор писать

                                Ноуп, при ивент-базед подходе в стор никто не пишет. Ну, точнее — в стор пишет только сам стор.


                                Delphin92


                                Потому что в этом случае компоненты нагружаются лишней логикой.

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


                                что компонент взаимодействует с окружающим миром не через пропсы

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


                                Конечно, при грамотной архитектуре и четком разделении на «умные» и «глупые» компоненты

                                А это вообще антипаттерн в том виде, в котором используется в реакте, т.к. ведет просто к появлению лишних оберток, которые, опять же — увеличивают сложность и затрудняют работу с кодом. Функция render сама по себе — это и так dumb component. Нет никакой пользы в том, чтобы выносить ее содержимое во вне.

                                  0
                                  Но ведь лучше, когда логика, нужная для работы компонента, содержится в этом компоненте.

                                  Речь идет о логике, которая нужна не для работы компонента, а которую этот компонент вызывает. Например, при клике на маленькую кнопку «запустить» может запускаться сложный расчет, опрашивающий несколько сервисов и формирующий данные, попадающие на форму. Все это держать в компоненте кнопки?

                                  Компонент — это слой представления. Все что он должен делать — рисовать UI и реагировать на действия пользователя. Так, конечно, не всегда получается, но к этому надо стремиться.

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

                                  Можете обосновать? Как именно это усложняет?

                                  Компонент должен получать через пропсы те и только те данные, которые он не может нормально получить по-другому.

                                  Компонент — функция. Какой есть нормальный способ передачи данных в функцию? Ее параметры. В случае реакта это пропсы.

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

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

                                  С каких пор введение дополнительных уровней абстракций и логического разделения по слоям затрудняет работу с кодом?

                                  Но в целом, для начала стоит определиться, что мы понимаем под «умными» и «глупыми» компонентами.
                                    0
                                    Речь идет о логике, которая нужна не для работы компонента, а которую этот компонент вызывает.

                                    Как же нет? Компоненту требуется получить какие-то данные — пусть и получает прям тут. Это же просто удобнее.


                                    Например, при клике на маленькую кнопку «запустить» может запускаться сложный расчет, опрашивающий несколько сервисов и формирующий данные, попадающие на форму

                                    Ну и точно так же будет
                                    const result = await getSomeData();
                                    someDataUpdated(result);


                                    Все ваши расчеты внутри getSomeData. И то что там что-то поменялось, никак вообще не повлияло на call-site.


                                    Все это держать в компоненте кнопки?

                                    А почему нет?
                                    У такого подхода ведь нет никаких минусов. Сидит эта функция getSomeData в компоненте и сидит — етьс не просит, никому и никак не мешает. Пока это удобно — держим в компоненте. Как только перестало быть удобно — собственно, выносим. Вытащить функцию из компонента — это самый примитивный рефакторинг, полминуты требуется. А если автоматически — то и вовсе несколько секунд.


                                    Компонент — это слой представления. Все что он должен делать — рисовать UI и реагировать на действия пользователя. Так, конечно, не всегда получается, но к этому надо стремиться.

                                    Стремиться надо к тому, чтобы код был прост, и с ним было легко работать. К бездумному следованию каргокульту стремиться не надо.


                                    Можете обосновать? Как именно это усложняет?

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


                                    Компонент — функция

                                    Компонент — это не функция. Он не является функцией и не работает как функция. Не над обманываться.


                                    Какой есть нормальный способ передачи данных в функцию? Ее параметры. В случае реакта это пропсы.

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


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

                                    Типичная вещь — вы пытаетесь оптимизировать работу редкого сценария, жертвуя работой типичных. Следует же поступать ровно наоборот — оптимизировать работу типичных сценариев, жертвую редкими.
                                    Зачем мне портить код ради того, чтобы иметь возможность приконектить компонент к другой части стора, если в 99 случаев из 100 мне это не понадобится? А когда понадобится — опять же, перемещение локальной части стейта в стор — это элементарный рефакторинг.


                                    Если компонент самостоятельно вытягивает данные из стора или еще как-то, это как минимум снижает возможности переиспользования.

                                    Опять же — в 99 случаях из 100 не будет никакого переиспользования, т.к. этот компонент нужен только в одном единственном месте и эти данные нужны только этому компоненту.


                                    (у меня как минимум один раз возникала такая необходимость)

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


                                    С каких пор введение дополнительных уровней абстракций и логического разделения по слоям затрудняет работу с кодом?

                                    С тех пор, как вообще придумали абстракции. Любая абстракция является тех. долгом и требует дополнительных затрат на свое сопровождение.
                                    Почему же абстракции вообще используют? Да потому что могут быть плюсы, перевешивающие эти минусы. При прочих равных же — абстракции всегда вредны. Не стоит применять абстракции просто ради абстракций. применять их стоит только в том случае, если вы можете ясно объяснить, почему данная абстракция нужна в данном конкретном месте. Как именно она вам упрощает жизнь. Если вы в явном виде сформулировать необходимость не можете — то нахер такую абстракцию, пишите простой код.


                                    Но в целом, для начала стоит определиться, что мы понимаем под «умными» и «глупыми» компонентами.

                                    Ну, я думаю, то же, что и все — если сформулировать попросту, когда у компонента нету своего состояния (т.е. компонент сводится просто к рендерингу) — то это компонент глупый. А если у него есть какое-то свое внутреннее состояние, которое он менеджит — то это компонент умный.

                                      0
                                      Стремиться надо к тому, чтобы код был прост, и с ним было легко работать. К бездумному следованию каргокульту стремиться не надо.

                                      Несомненно. И понимание, где искать тот или иной кусок кода — существенно упрощает работу с проектом. Когда логика в компонентах, приходится бегать по ним туда-сюда, чтобы найти, где она именно находится. Уже упомянутый пример расчета. Что-то будет в кнопке. Что-то в отдельной функции — мы же не любим говнокод и вынесем большой кусок, ведь верно? Что-то будет в формах, которые эти данные выводят. А уж если появляются какие-то всплывающие окошки, на которых тоже есть формочки и кнопочки… В итоге один и тот же, логически связанный функционал расползается по разным файлам и очень сложно собрать все в голове воедино.

                                      Отсюда и вытекает данная максима. Компоненты — только для отрисовки и обработки действий. Любая бизнес логика должна быть вынесена с самого начала, а не когда у вас появится желание и возможность провести рефакторинг.

                                      Да например — вот если у меня ф-я внутри компонента или там импортирована из какого-то файла, то я жму ctrl+click и попадаю на ее реализацию.

                                      Согласен, в данном случае пропсы несколько усложняют жизнь. Но если следовать описанному выше правилу, таких вызовов в компоненте у вас будет 2-3. Иначе вы уже что-то делаете не так. Поэтому достаточно посмотреть в конец файла, где connect, и ctrl-click-нуть там.

                                      Зато вы можете сразу видеть, с чем именно работает ваш компонент. Это все описано в connect. Вам не надо лазить по обработчикам чтобы увидеть, что же именно они там вызывают.

                                      А еще любая ф-я может захватывать параметры из своего лексического контекста (ака замыкание).

                                      Погодите. Если вам нужно замыкание — используйте замыкание. Оно прекрасно помогает сократить количество кода для вспомогательных компонентов. Вы же говорите не о нем. Вы, фактически, топите за использование глобальных объектов внутри функции.

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

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

                                      перемещение локальной части стейта в стор — это элементарный рефакторинг

                                      При чем здесь локальный стейт? Локальный стейт действительно, часто оправдан.

                                      Ну, я думаю, то же, что и все — если сформулировать попросту, когда у компонента нету своего состояния (т.е. компонент сводится просто к рендерингу) — то это компонент глупый. А если у него есть какое-то свое внутреннее состояние, которое он менеджит — то это компонент глупый.

                                      Вот с этого надо было начат, потому что я под эти понимаю совсем иное. Глупый компонент — который ничего не знает об окружающем мире, заточен под работу с пропсами и нацелен на переиспользование. Умный — понимает, зачем он здесь, в каком контексте будет использован. Общается с внешним миром и может выполнять дополнительные действия, не связанные с рендерингом (увы, это приходится делать).

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

                                        Именно! вот я и топлю за это. Найти код в редакс-лапше — нетривиальная задача. Когда же код просто написан в том месте, где используется — это легко и очевидно, тут даже искать ничего не надо. Максимум — вы все найдете, сделав ctrl+click. Иде решит проблему за вас.


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

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


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

                                        совсем не должна. Код следует усложнять (= снижать его качество) только тогда, когда непосредственно это требуется. Зачем сразу наращивать тех. долг?


                                        Согласен, в данном случае пропсы несколько усложняют жизнь.

                                        Это "несколько усложняет жизнь" в итоге приводит к завышение затрат по некоторым задачам в разы.


                                        Поэтому достаточно посмотреть в конец файла, где connect, и ctrl-click-нуть там.

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


                                        Обращаю внимание, что во многих описанных местах трудозатраты на поиск существенно выше контрол-клика, более того — в некоторых случаях у вас может просто не быть нормальных типов (их не написали, либо код абстрактен — и явных зависимостей по ссылкам просто нет!) — это означат, что поддержка со стороны тулинга вырублена, и задача "найти экшон, который апдейтит данное поле" легко превращается в расследование на целый рабочий день.


                                        Погодите. Если вам нужно замыкание — используйте замыкание.

                                        Так метод объекта — это просто обычное замыкание.


                                        Вы же говорите не о нем. Вы, фактически, топите за использование глобальных объектов внутри функции.

                                        Глобальное состояние внутри функции — это как раз редакс.


                                        И, кстати, нет ничего плохого в глобальных объектах. И не было никогда. Плохое — это глобальное состояние.


                                        Однако я не сказал бы, что как-то страдают типичные сценарии.

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


                                        Передача всех данных через пропсы (замыкания мы не берем) имеет определенные преимущества.

                                        Она не имеет ни одного преимущества. Но имеет уже описанные выше недостатки.


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

                                        Это просто неправда. Функции типизировать удобнее, чем компоненты. просто потому, что типизация ф-и — это нативное средство языка со всеми вытекающими.


                                        При чем здесь локальный стейт?

                                        Ну мы же это и обсуждаем — перенос локального стейта в редакс.


                                        Вот с этого надо было начат, потому что я под эти понимаю совсем иное.

                                        Т.е. вы понимаете что-то свое, уникальное. Тогда и придумайте свой термин. А общепринятые термины следует использовать в их общепринятом значении.


                                        Глупый компонент — который ничего не знает об окружающем мире

                                        Любой компонент, у которого есть пропсы, знает об окружающем мире. На этом, думаю, можно и закончить.


                                        Если бы существовал ровно один правильный способ что-либо сделать — наша профессия была бы значительно проще.

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

                                      –2
                                      Если компонент самостоятельно вытягивает данные из стора или еще как-то, это как минимум снижает возможности переиспользования.

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

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

                                      Что за бред? Сколько проектов вы успели реализовать? Один? Каждый день через пропсы меняете редакс, на хренакс и обратно?
                                      Что за фантастика. Вроде смешно, но блин вы на полном серьезе такое пишете, а это уже грустно.

                                      С каких пор введение дополнительных уровней абстракций и логического разделения по слоям затрудняет работу с кодом?

                                      Ахахаха, вы точно не по приколу такое пишете? Может всё таки прикалываетесь? (Надеюсь на это очень)

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


                                      Можете обосновать? Как именно это усложняет?


                                      Ахахха, не ну 100% троллите.
                                  –1
                                  А зачем, если можно просто написать...

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

                                  Конечно, при грамотной архитектуре и четком разделении на «умные» и «глупые» компоненты можно действовать и таким образом, но в общем случае это приводит лишь к запутыванию.
                                    0
                                    но все равно получается, что компонент взаимодействует с окружающим миром не через пропсы, а какими-то другими, не столь явными путями. А это не есть хорошо.

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

                                    Хах, ну тут вообще фиаско.
                                    Вот это не очевидно и как-то не явно? Прям вот вообще не понятно откуда что импортируется, да? Что там есть вообще? Что делает да?
                                    import React, { useState } from 'react';
                                    import { MyComponentState, globalTitleState } from './state';
                                    
                                    import styles from './styles.module.scss';
                                    
                                    export const MyComponent = observer(() => {
                                        const [state] = useState(() => new MyComponentState());
                                    
                                        return (
                                            <div className={styles.some_style}>
                                                <h1>{globalTitleState.title}</h1>
                                                <input onChange={globalTitleState.handleTitleChange} />
                                                <h2>Counter: {state.counter}</h2>
                                                <button onClick={state.incrCounter}>Incr counter</button>
                                            </div>
                                        );
                                    });
                                    

                                    Где MyComponentState и globalTitleState
                                    import React from 'react';
                                    import { observable } from 'mobx';
                                    
                                    
                                    export class MyComponentState {
                                        @observable counter = 1;
                                    
                                        incrCounter = () => {
                                            this.counter++;
                                        }
                                    }
                                    
                                    class GlobalTitleState {
                                        @observable title = 'some title';
                                    
                                        handleTitleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
                                            this.title = e.target.value;
                                        };
                                    }
                                    
                                    export const globalTitleState = new GlobalTitleState();
                                    


                                    Вообще всё так не явно, не понятно и запутанно. А главное сложно и поддерживать не возможно. Да, понимаю. Похоже это доступно только избранным да?

                                    Конечно, при грамотной архитектуре и четком разделении на «умные» и «глупые» компоненты можно действовать и таким образом, но в общем случае это приводит лишь к запутыванию.

                                    Слова из 2014 года, в реакте все компоненты тупые и должны быть только тупыми. Они зависят только от состояния приложения и внутреннего состояния самих компонентов. А это состояние разумеется должно управляться не реактом, т.к. оно убогое. А другим инструментом.
                                      +1
                                      Вообще всё так не явно, не понятно и запутанно. А главное сложно и поддерживать не возможно.

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

                                        –1

                                        А ещё все это должно пройти через 10 action creator'ов, фабрик и саг. И тогда будут потребности извращенцев удовлетворены)) Ну и разумеется передано пропсами через десяток другой компонентов)) Ведь писать простой и очевидный код это удел только дурачков. А настоящие профессионалы пишут код так, чтобы вообще никто и никогда в нем не разобрался, чтобы особенно подчеркнуть свою крутость, мол для вас это говнокод и дичь, а я же вот его написал и оно даже как-то работает, а вы просто дурачки если не понимаете. Вот так похоже мыслят любители редакса, саг, санок, еффектора и прочей ереси.

                                          0

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

                                            +1

                                            Ох, как злободневно — вот недавно поработал с проектом на Mobx, но пока разберешься как это все сделано… 20 быстрых переходов по пропсам компонента — и то в абстрактную фабрику, то в ООП-шный класс, унаследованный от нескольких других классов, то в "нормализованный" entity-стор, то в многотомные типы, то в обертку для сериализации-десериализации, то в файлы-помойки на тысячи строк, содержащие никак не связанные данные… Я бы мог понять еще 2-3 перехода до финального хранилища и типа, но когда вот так вот и с большими объемами кода — это как-то за гранью адекватного. Для меня это дичь, для них — синьорский код с десятком паттернов. А функционал-то обычный, получить данные и отформатированно отобразить в интерфейсе. Не в клозетах разруха, как говорится

                                              –1
                                              вот недавно поработал с проектом на Mobx, но пока разберешься как это все сделано

                                              Вы уверены что дальнейшее описание про MobX? =) Если да, то это новый вид извращенцев ранее не известный человечеству)
                                              Потому что вы описали типичный говнокод react+redux «разработчика»
                                                0

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

                                                  0
                                                  Ааа, ну это вообще тяжелый случай :D
                                                    0

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

                                                      –1
                                                      (архитектура ангуляра достаточно жестко ограничивает подобное говно). Это как раз типичный реакто-подход в своем первозданном виде.

                                                      Где-то плачут тонны типичных react+redux «разработчиков», которые пишут так по сей день :D
                                      0
                                      Не могу не влезть со своим вопросом: без useSelector все равно не обойтись при описании view?

                                      Просто если в коде использую конструкцию вроде
                                      <p className={getState().stats.page[index].active[0]}>Futures</p>
                                      код не реагирует на изменение в глобальном сторе, или connect сделает какую-то магию и просто нужно лучше читать описание?

                                      (Пока не понял зачем нужен connect и просто так или иначе пробрасываю store.dispatch и store.getState либо store в компонент)

                                      Заранее спасибо за ответ.
                                        +1
                                        Connect магию не сделает — он просто передаст указанный срез store-а в props-ы компонента. В итоге при изменении стора изменятся пропсы и react отреагирует ререндером.

                                        В случае обращения к getState напрямую — не будет изменения пропсов, не будет ререндера. Может быть, можно как-то выкрутиться через прокси, обсерверы, но это будет уже совсем не в концепции redux.
                                          0
                                          Еще раз спасибо.
                                          А зачем через Connect передавать onUpdateData?
                                          Если я просто импортирую нужные thunk-овские action-ы в компонентах что-то пойдет не так?
                                            0
                                            Всегда пожалуйста)

                                            Вы можете писать dispatch(doAction(args)). Все будет работать. Экшены передаются в connect чтобы превратиться в пропсы — для единообразия и возможного переиспользования компонента. Т.е. в этом случае для компонента нет разницы, подключен он к редаксу или нет, он оперирует исключительно своими пропсами и локальным стейтом, если есть. А вся связь с редаксом выносится в connect.

                                            И да — thunk-овские экшены с точки зрения вызова не отличаются от обычных — в этом как раз и заключается его удобство.
                                              –1
                                              в этом как раз и заключается его удобство

                                              Удобство, ага :D
                                              Смешно и абсурдно в контексте redux и его «друзей» слово удобство.
                                                0
                                                В некоторых распространенных кейсах редакс является единственным выбором (например, команда ведущая разработку на редакс ищет еще одного программиста)
                                                  –1
                                                  В некоторых распространенных кейсах редакс является единственным выбором

                                                  В смысле?? В каких это ещё кейсах??
                                                  Нету вообще ни одного кейса где не справится MobX, но справится редакс.
                                                    0
                                                    Наверное я неоднозначно написал: если команда уже ведет разработку на редакс и ищет еще одного программиста, то этому самому программисту подойдет только редакс. Не будет же никто из-за желания кандидата переводить существующий проект на моб-икс
                                                      –1
                                                      Не будет же никто из-за желания кандидата переводить существующий проект на моб-икс

                                                      С чего вы это взяли? Ещё как будут, проверено на практике неоднократно, как мной, так и моих друзей программистов начиная с 2016 года.
                                                      Кому покайфу утопать в говнокоде redux подхода?
                                                      Правильно, никому кроме мазахистов конечно.
                                                      Поэтому с удовольствием все переписывают на MobX.
                                                      Но опять же, если вас собеседует команда мазахистов, а вы таковым не являетесь, то врятли вам стоит соглашаться на работу с ними. Но это конечно ваше личное дело. Но это не мой выбор.
                                                      Есть ещё вторая каста мазахистов, которые считают что голый react вообще лучше чем react + стейт менеджер. Это тоже те ещё кадры конечно.
                                                        0
                                                        Если Вы приходите как лоурейтовый фрилансер — на такого ориентироваться не станут ))
                                                        Да и на временной работе Вам не все ли равно? Оплата-то от этого не зависит
                                    0
                                    Предвосхищая вопросы — mobx я пробовал, не понравилось.

                                    Не понравилось?
                                    Почему? Что с ним не так? Чем он менее удобен, чем Redux? чем Redux лучше его?
                                      +1
                                      Проект был года полтора назад, поэтому подробности уже забылись. Из того что помню — было сложно работать с мутабельными объектами. Если в redux я могу законнектить любое поле стейта, затем поменять сразу весь родительский объект и все будет работать, то с mobx постоянно приходилось следить, что можно менять, а из-за чего observer-ы поотваливаются.

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

                                        Я так и думал. Ничего не помню, ничего не знаю, разумеется никакого кода и конкретных примеров не приведу, но он мне не понравился.

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

                                        Вмысле сложно? Вы прикалываетесь? Или просто кидаетесь терминами, что якобы мутабильность это сложно и плохо. Ключевое слово сдесь якобы.
                                        Если в redux я могу законнектить любое поле стейта, затем поменять сразу весь родительский объект и все будет работать, то с mobx постоянно приходилось следить, что можно менять, а из-за чего observer-ы поотваливаются.

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

                                        Какие функциональные обертки? Приведите любой конкретный кейc и я покажу вам как надо это делать в MobX. А не так, как вы это видели где-то в каком-то говнокоде.

                                        Столько слов, ни одного по факту, только выдумки и смутные воспоминания. Если вы говорите не работает, отваливается, прям код напишите самый простой на котором не работает или не отваливается и тогда это уже будет другой разговор. Желательно сразу в codesandbox.io чтобы быстренько мог любой человек проверить его на правду. А я мог бы быстренько и легко подправить и скинуть ссылку и показать как надо делать, а не так, как вы думали что надо делать. И может вы бы тогда пересмотрели свои взгляды.

                                        А просто языком молоть, это всё что угодно можно говорить. Всё должно подтверждаться экспериментами, в нашем случае кодом)
                                          0
                                          Знакомые все лица :)
                                          Минус MobX в том, что на Upwork заказчикам нужен Redux, который теперь и качаю вместо более простого MobX.
                                          Хотя может их пугает мой говнокод, как знать
                                          (Одностраничное приложение, Код)
                                            +2

                                            Охох, спасибо за ссылку на код, всколыхнуло моего перфекциониста) Попробовал разобраться в


                                            if (this.rules.filter(rule => rule.symbols[0] === this.rules[ind].new_symbols[0]).length +
                                                        this.rules.filter(rule => rule.new_symbols[0] === this.rules[ind].new_symbols[0]).length +
                                                        this.machine[this.history_pos].tapes[0].tape.filter(frame => frame === this.rules[ind].symbols[0]).length > 1) {
                                                        if (this.symbols.filter(st => st.name === val).length === 0) {
                                                            this.symbols.push({name: val, description: ''});
                                                            this.rules[ind].new_symbols[0] = this.symbols.length - 1;
                                                        } else {
                                                            this.rules[ind].new_symbols[0] = this.symbols.findIndex(st => st.name === val);
                                                        }
                                                    }

                                            Получилось


                                            const getRulesBySymbol = (symbol) => this.rules.filter(({symbols}) => symbols[0] === symbol;
                                            const getRulesByNewSymbol = (symbol) => this.rules.filter(({new_symbols}) => new_symbols[0] === symbol);
                                            const getTapeBySymbol = (symbol) => {
                                                const currentTape = this.machine[this.history_pos].tapes[0].tape;
                                            
                                                return currentTape.filter(frame => frame === symbol);
                                            };
                                            
                                            const targetRule = this.rules[ind];
                                            const targetSymbol = targetRule.symbols[0];
                                            const targetNewSymbol = targetRule.new_symbols[0];
                                            
                                            const tapeBySymbol = getTapeBySymbol(targetSymbol);
                                            const rulesBySymbol = getRulesBySymbol(targetNewSymbol);
                                            const rulesByNewSymbol = getRulesByNewSymbol(targetNewSymbol);
                                            
                                            const symbolIndex = this.symbols.findIndex(st => st.name === val);
                                            const hasSomeRecords = [rulesBySymbol, rulesByNewSymbol, tapeBySymbol].some(arr => Boolean(arr.length))
                                            
                                            if (hasSomeRecords) {
                                                if (symbolIndex === -1) this.symbols.push({
                                                  name: val, 
                                                  description: ''
                                                });
                                            
                                                targetRule.new_symbols[0] = symbolIndex === -1 ? this.symbols.length - 1 : symbolIndex;
                                            }

                                            Соответственно, почти все легко выносится в mobx-computed-геттеры и computedFn функции, в итоге может получиться достаточно лаконичный и читаемый код. А в изначальном варианте, конечно, сложновато было словить смысл… Я в целом к тому, если еще грамотней использовать mobx то получится вообще красиво.

                                              0
                                              Всегда пожалуйста и спасибо за красивый код. Но правильные решения сейчас — не моя тема.
                                              Быть может Vue + Next (или вообще — питон) + какая-то классическая СУБД с SQL куда проще и не потребует больших усилий на изучение с написание кода. Но увы — народу нужны наиболее используемые решения и новичку не остается ничего как следовать за модой.

                                              Мощь React и Angular большинству проектов не нужна, говорят Next продвинутее Expess-а, прямые SQL запросы на самом деле куда проще чем mongoose — SQL хоть и разный но логика работы в целом одинаковая и не меняется годами (десятилетиями?) и дает плюшки в виде нормализации, транзакций и продвинутого поиска, а изучив mongoose получу только возможность работать с mongodb из JS, и даже транзакций и блокировок из коробки не предоставлено, а как сменится тренд — все кинемся изучать какую-то еще обертку для СУБД.

                                              Но рынок есть рынок — легкое (легкое ли, если говорить о React и Angular?) вовлечение больших масс вообще не имевших опыта программирования и легкая замена персонала при стандартных решениях делают свое дело — в основных трендах веб-разработки мы имеем MERN/MEAN и SQL+PHP+JS (но там просто дичайший объем легаси, да и прочти все новые ниши достаются MERN/MEAN).

                                              Ох, кажется опять эмоциональная простыня получилось, спасибо всем кто дочитал до этого места. Но думаю я зря жалуюсь — людям вообще не знакомым с классическими ЯП и SQL (коих в веб-разработке, по крайней мере с началом пандемии, толпы) еще сложнее и для них быстрая смена трендов — норма, что страшно.
                                                0

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


                                                А по второй части, где про то, что много осталось кодовых баз на php и хочется какой-то стабильности, чтобы все на одном языке и в одном подходе писали — это нереалистично на данном этапе, когда технологии активно развиваются. Может лет через 20 и устаканится, хотя что делать со всеми старыми кодовыми базами — непонятно. Тут либо развиваемся и что-то оставляем в прошлом, либо страдаем от ограничений устаревших решений.

                                                  0
                                                  Хочешь сказать, что красивый современный интерфейс — почти главное во фронтенде? Быть может, быть может. Просто цимус в том, что простой JS то никто не хочет — всем нужно React/Angular или целый MERN/MEAN даже там где простая форма без особой логики и можно обойтись HTML и парой функций на jQuery.

                                                  По поводу MERN — не такой уж это и фронт, там и бэкенд нехилый. Вообще сложилось ощущение, что для полноценного использования MERN нужно несколько специалистов: один придумает UI и сверстает/напишет нормальный вьюв с эффектами, второй сделает его реактивным, наполнит логикой и подцепит управление состоянием, а третий сделает бекенд на каком-нибудь Express(Nextjs?). Возможно я не прав, но имхо даже фуллстек с хорошими знаниями какой-то этап сделает хуже.

                                                  P.S. параллакс меня лично укачивает а лайтбокс бесит, хотя на телефоне, наверное, смотрятся красиво. А вот модалка, слайдер и селект штуки красивые и полезные, если не злоупотреблять — тут не могу не согласится: сделать их как таковые в общем-то не проблема, но в анимацию и красивый дизайн я пока не умею, это правда.
                                                  Собственно попробовал materialize css, но там элементов кот наплакал, правильнее наверное сразу использовать Bootstrap с шаблоныами.
                                                    0

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


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


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

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

                                                      С тем что JS основа — невозможно спорить. Я о другом — рынку нужны стандартные решения с качеством не хуже стандартного, потому что сколь угодно совершенное оригинальное решение без разработчика дешевле заменить целиком чем пытаться найти другого специалиста который потратит n-ное количество времени на то чтобы вникнуть. По крайней мере так во фрилансе.
                                                      Отсюда и тяга к React/Redux. Говнокод возник собственно из-за того, что я занизил планку качества кода — просто мне все равно насколько хорош или плох сам код, пока это устраивает того кто платит, но видимо на демке лучше дать код высокого качества.

                                                      Фуллстек — тема. Там и заказов больше — не обязательно же каждый раз реализовывать полный стек, можно встроится в большее число команд, правда при этом стоит будет такой фуллстаковец дешевле (как нуб на какой-то части, ага) но это лирика.
                                                      Да и фуллу открывается больше веток развития когда найдет свое место на рынке.

                                                      Про перегрузку головы это точно и то что язык везде один не спасает — так и хочется вставить в Express thunk-овский action, а потом вспоминаю, что тут нет столько ограничений на асинхронность и места вызова как в React/Redux.
                                                        0

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


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

                                                          0
                                                          Каждый выбирает, что ему по душе, мне принцип фриланса ближе, а то что подходы неэффективные — так кто платит тот и заказывает музыку :)
                                                          Хотя Redux действительно ужасен.
                                            0
                                            Ну ж извините, ссылочку на проект я не кину. Могу написать название. Программный комплекс обработки документов, поступающих от налоговых органов в рамках Положения Банка России № 440-П для Альфа-банка. Конкретно — АРМ.

                                            Вы требуете от меня потратить пару часов времени на то, чтобы вспомнить mobx, вспомнить или найти в гите какие возникали проблемы, оформить все на codesandbox.io… И ради чего?

                                            Заметьте, я не говорю что mobx отстой или типа того. Я говорю что лично мне redux понравился больше. А крики «вам он не должен нравиться» — это уже какой-то детский сад.
                                              –1
                                              чтобы вспомнить mobx

                                              найти в гите какие возникали проблемы

                                              Ахахах, ну классика. Ответы прям как по учебнику по соскакиванию от ответов на конкретные вопросы. Ведь проблем то нет и не было. Только ваши фантазии. Удобно прикрываться за "да я забыл, дело было давно, но однозначно все было плохо именно из-за технологии, а не потому что у нас руки растут не понятно откуда".
                                              Такие вещи запоминаются до долгие годы, я хорошо и отчетливо помню какую боль и страдания приносил мне и мои товарищам по команде redux, саги, санки, реселекты и прочая нечисть. Хотя это было в 2014-2015 годах, хорошо что ума хватило с 2016 года и по сей день пользоваться MobX'ом, чтобы перестать бороться и начать разрабатывать и получать удовольствие. А не утопать в тоннах говнокода растущего с геометрической прогрессией.

                                              Я говорю что лично мне redux понравился больше.

                                              Это же просто слова, не несущие сути или пользы. Вы же не привели ни одного настоящего аргумента против.
                                              Как вам может что-то понравится больше, если вы в реальности не сравнивали X и Y, чтобы утверждать, что мол вот я попробовал X и Y, но вот X мне понравился больше, потому что он лучше чем Y тем-то тем-то, а ещё в Y ещё есть проблемы с тем-то тем-то.
                              +5
                              Фреймворк задаёт структуру и подход к архитектуре вашего приложения, он диктует, как вы должны писать код.

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


                              Почему же библиотекой а не фреймворком для отображения данных? Структуру он вполне задает и явно диктует как мне нужно писать код(попробуйте написать любое приложения без использования хуков его Lifecycle).
                                +2
                                Понимаю, что тут смутило. В определении фреймворка подразумевалось, что он отвечает за архитектуру и структуру не только слоя представления, как правило слой представления нуждается в меньшей «архитектурности», а больше за архитектуру бизнес слоя и приложения в целом, включая слой сервисов и прочего. Реакт диктует же именно как писать компоненты, но как их компоновать, как структурировать, это дело падает на плечи пользователя инструмента.

                                Ну и плюс React сам говорит: «я библиотека» — «A JavaScript library for building user interfaces».

                                Рассматривать отдельные подсистемы как фреймворки — перебор, как минимум для данной статьи, что может смутить начинающих разработчиков. В остальном конечно react можно считать чем-то большим, чем библиотеку, для кого-то это действительно фреймворк, если помимо отображения использовать Context API для управления данными
                                  +1
                                  Ну хорошо, положим что Реакт не дотягивает до SPA фреймворка. Что насчет vue? Разве там можно из коробки управлять глобальным стейтом и писать роутинг? Насколько я знаю для этого есть соответствующие либы vuex и vue-router которые идут отдельно? Почему же Vue называют фреймворком?
                                  А что у svelte? У него есть в комплекте роутинг и работа со сторами уровня Redux/vuex или опять пишите депенденсы?
                                  Получается что либо у нас единственный фреймворк angular(JS), либо просто учитываем то что написал автор на офф странице.
                                    +3
                                    Тут есть несколько поинтов.
                                    1) У Vue есть встроенный store pattern, который позволяет управлять стором, при этом Vue не преследует концепцию единого глобального стора, поэтому сторы могут быть атомарными, Vuex — концепт единого стора, аля Redux, созданый для того чтобы понизить уровень сложности миграции комьюнити c React/Redux на Vue/Vuex, да и в принципе данный концепт хорошо себя показал, как многие считают, отсюда и появление инструмента.
                                    2) Практически тоже самое у Svelte, так как наследовали свои лучшие практики они (Svelte + Vue) у одного прородителя, насколько помню, Reactive.js
                                    3) react-router не относится напрямую к монорепе react, даже к неймспейсу. Исторически react context api был статическим, сейчас его называют legacy context api, новый context api не поменял концепт react, поэтому не произошло переименования библиотеки во фреймворк. Vue + vue-router поставлялись как правило вместе и входили в один неймспейс vuejs на github, которые давали вместе полноценный фреймворк, Vuex — не в счет, он появился позже.

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

                                    На самом деле, как не назови все эти инструменты, решают они одни и теже задачи и взаимозаменяемы ввиду развития фронтенда.
                                +1
                                А что скажете про ui фреймворк webix, можете предложить альтернативы ему?
                                  0
                                  Разве про EXTJS не слышали?
                                    +2
                                    Это немного за рамками этой статьи, но UI фреймворки типа Webix, Bootstrap, Foundation, Material UI, Antd и прочие решают именно проблему готовых компонентов и быстрой сборки представления.
                                    Альтернативы описал выше, но опять же, часто каждый из UI фреймворков, ровно как и интсрументов описанных в статье имеет свои особенности, в число таких Webx отличает наличие неплохих pivot таблиц, мы даже их использовали на одном из проектов.
                                    Как правило альтернативу выбирают по принципу, покрывает ли UI фреймворк ваши компоненты которые используются в проекте, сложность интеграции и другие особенности, как вес бандла (tree-shaking), сложность API, использование конкретного препроцессора внутри, возможность расширения.
                                    Все зависит от того, какую задачу на данный момент решает у вас Webix, а так очень часто на современныз проектах встречаю больше и больше Material UI.
                                    +2

                                    К минусам angularjs, за который его тоже осень сильно ругают, стоит отнести работу с контекстом, он же $scope в терминах angularjs.

                                      +2
                                      По работе со $scope было много специфики, насколько уже сейчас помню. Некоторые из них, такие как коллизии имен переменных при использовании нескольких контроллеров в одном шаблоне, уходили при использовании controllerAs синтаксиса, да и в контроллерах можно было уходить от $scope к this. Помимо $scope, очень не нравился подход написания директив и их области видимости, но не стал заносить все это в недостатки, чтобы не уходить в глубокую специфику инструмента.
                                      +3

                                      Казалось бы, к концу 2020 года пора бы перестать спорить об отличиях фреймворка от библиотеки и сравнивать их между собой. Все фреймворки хороши – выбирай на вкус!

                                        +3

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


                                        Сложности тестирования, на каждый простой чих нужно написать тонну кода, отсуствие внятной архитектуры, отсутсвие two way binding и многое другое.

                                          +2
                                          Спасибо маркетингу Facebook, React в любом случае показал новые подходы к написанию кода, может и не самые лучшие и в других инструментах они были удобнее, да и есть. Тем не менее на момент выхода интересный концепт реактивного программирования + хороший маркетинг IT гиганта сделали свое дело, а дальше это снежный ком все сложнее останавливать.

                                          По сложности тестирования именно React компонентов скажу, что уже как года 3 перестал их тестировать именно unit-тестами с jest-снапшотами, более эффективно получается писать компонентные тесты с использованием скриншотов.

                                          Касательно тонн кода, отсутствия внятной архитектуры и другого, это я и попытался занести в недостатки (но с другой стороный может быть и +, смотря как на это смотреть). Это действительно не работа React и он не покрывает слой бизнес логики и не старается, и когда мы берем данный инструмент, оказывается, там много чего не хватает из коробки и мы пускаемся в увлекательное путешествие в гугл =)
                                            +3
                                            Не все, например, React незаслужено популярен.
                                            Подходы и решения в нем больше похожи на костыли чем на обдуманные решения.

                                            Сложности тестирования, на каждый простой чих нужно написать тонну кода, отсуствие внятной архитектуры, отсутсвие two way binding и многое другое.

                                            Если использовать реакт не только как view слой, но и управлять с помощью него состоянием приложения, то да, это полнейшее дно.

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

                                            Но если использовать реакт только как view слой в связки с MobX, то это уже становится совершенно другой, можно сказать отдельный инструмент. И тут уже подходы и код получается совсем другой, небо и земля. Максимальная гибкость, отсутствие ограничений, минимальное кол-во кода, полный простор для творчества и реализации по настоящему крутых архитектурных решений.
                                              +2

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

                                                0

                                                Тяжело супортить, тяжело расширять, тяжело тестировать. Очень плохая поддержка от команды реакт. Просто тот же Angular проще и лишен этих недостатков. (я говорю про проекты Энтерпрайз уровня, может для одностраничников ситуация другая)

                                                  +2
                                                  А в чем не устраивает поддержка от команды React? на мой взгляд ребята наоборот делают очень крутую обратную совместимость между минорными и даже мажорными версиями.

                                                  Что касатся сложностей при саппорте, расширении и тестировании. Я как понимаю речь то идет не про слой представления, чем и является React, а в принципе про приложения написанные на React и связанной экосистеме? Если так, то сама экосистема очень богатая, не нужно упираться в дефолтный React-Redux, есть куча альтернатив:
                                                  — React-MobX
                                                  — React-Effector
                                                  — React-Reatom
                                                  — И для самых консерваторов React-EventEmmiter
                                                  Просто из этого списка можно выбрать наиболее удобное для себя решение по критериям масштабирования, кол-ву бойлерплейта, простоте тестирования.

                                                  Как человек, который использует React с 2014 года и писал только жнтерпрайз на нем, скажу, что нет с этим никаких проблем. Но Angular действительно имеем богатую экосистему и поставляется в виде batteries included решения, поэтому очень популярен в ентерпрайз проектах.
                                                    +1

                                                    А можно больше конкретики? Пока это больше выглядит как хейт

                                                  +2

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


                                                  В вебе существует большая проблема — статичность интерфейсного слоя и сложность взаимодействия с ним, JSX предоставляет возможность писать околостандартный HTML в JS с возможностью выполнять логику в жизненном цикле, выводить переменные, разбивать на компоненты, делать изоморфный рендеринг. По сравнению с другими dom-sync-подходами здесь намного меньше кастомщины и хаков (v-if="some logic in strings?!", @click="stringRefToFunction") и отсутствие "детских болезней", т.к. сообществом выработаны эффективные практики.


                                                  Все остальное — FLUX, props drilling, отсутствие эффективного стейт-менеджмента и встроенных библиотек для DI, роутинга и т.п. — это другие области, в которых использовать голый React неэффективно. И это не недостаток, а свобода в выборе решений. Да, мы часто пишем в комменты про MobX, т.к. он позволяет максимально минимизировать boilerplate, сделать явный направленный поток данных view-action-store, просто сочетается с разбиением по чанкам и SSR, предоставляет autorun-подписки для сайд-эффектов. В сочетании с простой и эффективной реактовой схемой описания компонентов эти инструменты покрывают большинство сценариев, которые могут потребоваться во front-разработке. В общем, претензии могут быть только при использовании Реакта не по назначению (а сюда я включаю использование подходов, придуманных его разработчиками, которые напрасно пытались расширить сферу его применения, вместо специализирования на dom-sync-функционале). Отсюда в обиход вошел термин react-way, который означает "так как бы правильно by design, но совершенно неудобно" и многие упираются в легко предсказуемые проблемы, который этот react-way привносит.


                                                  По поводу тестирования — в промышленных проектах используются на 90% интеграционные тесты, и на 10% юниты для утилит и функций преобразования данных, тестирование отдельных компонентов на моковых данных дает слишком мало гарантий. Так что соглашусь отчасти — реактовые компоненты изолированно тестировать сложно, но это и не нужно.

                                                    0
                                                    меньше кастомщины и хаков (v-if="some logic in strings?!", @click="stringRefToFunction")
                                                    Поясните поподробнее. Лично у меня опыт с React+JSX привёл к тому, что всё смешалось в кучу, и разметка, и логика. Из-за этого нужно было на каждый чих долго и мучительно выносить всё в подкомпоненты. В случае с Vue шаблон сам получался минимально простым и дробить на компоненты оказалось существенно проще и куда реже возникала в этом необходимость. Так что «хаки и кастом» тут по мне вполне оправданы. Но может я не понимаю, как комьюнити решает подобные проблемы.

                                                    Ещё одна личная претензия к реакту — неумение работать с вложенными изменениями из коробки, но тут можно понять чем это продиктовано и написать/найти обёртку.
                                                      0

                                                      В кучу можно при любом подходе смешать, я говорил про синтаксис. Реактовый {isShown && <Component />} в моем понимании выигрывает у вьюшного v-if="isShown" по критериям: в первом случае синтаксис джаваскриптовый и может быть вынесен за пределы рендера, во втором — строковый, который работает схоже с eval, и должен присутствовать в тегах элемента; в первом кастомных тегов нет и изучать нечего, во втором — нужно изучать документацию и специфику работы.


                                                      Таких семантических историй накапливается довольно много, а для динамики HTML вполне достаточно обойтись внедрением в него JS-синтаксиса и компонентов, все остальное — излишества. Ну и известные фреймворки не ограничиваются кастомными тегами, а еще вводят переменные с $, @, # и т.п., которые работают с особой логикой. Ну и TS с этим слабо работает, так как строка в дата-атрибуте — есть строка, а в JSX это ссылка на переменную, соответственно рефакторинг проще. Я не настолько глубоко изучал Vue, но на базовых примерах сталкивался с перечисленными проблемами в системе шаблонизации.


                                                      Дробление на компоненты в Реакте мучительно, а во Vue просто? Во Vue можно писать длинные неразбитые по компонентам шаблоны? Видел я такое в проектах (Angular), шаблоны по 500-1000 строк, но думал подобное уходит в прошлое и сейчас стремятся к большей атомизированности с целью переиспользования и упрощения контроля. Да, Реакт плохо оптимизирован для рендеринга таких вот больших компонентов, и придуман ряд подходов для блокирования перерендера дочерних компонентов: PureComponent (подходит для случаев, когда пропы равны по ссылкам), shouldComponentUpdate (для сложных сценариев), Mobx.observer (для глубокого сравнения пропсов, не считая функций, с функционалом трекинга и перерендера), Redux.connect (тоже имеет встроенный SCU). Соглашусь, что можно было бы сделать коробочный вариант для deep compare props, но большой проблемы в этом не вижу.

                                                        0
                                                        сейчас стремятся к большей атомизированности с целью переиспользования и упрощения контроля

                                                        Атомизированность приводит к проблемам управления стейтом и тому самому props drilling. При этом снижая возможности переиспользования и уменьшая контроль, что характерно.
                                                        Маленькие компоненты в реакте — проблема, редакс в реакте — проблема, но не дай бог вам увидеть проект в котором будут "атомизированные" компоненты и массивное использования редакса со сваливанием всего в его стор, тут проблема не к квадрате — это экспонента проблемы.
                                                        Задачи, которые в "компонент на тыщу строк" решаются без каких-либо проблем за час, в подобной вермишели из кода требуют, бывает нескольких дней работы.

                                                          0

                                                          Думаю, не совсем так...


                                                          1. Компонент в тыщу строк — прост в поддержке?
                                                            Я не раз видел такие компоненты, как правило в них очень много бизнес-логики, которая должна была бы быть в других слоях + очень много разметки и стилей, которые во многом дублируются по проекту. При разбиении на удобные блоки дубляжа кода будет меньше, изучение этих более мелких компонентов будет проще, правка багов в них приведет к их исправлению во всех местах, где используются эти компоненты. Налицо снижение сложности, уменьшение времени на правки, уменьшение количества кода, улучшение производительности (при SCU у чайлдов)


                                                          2. Редакс в Реакте — проблема, а если еще и подключен к мелким компонентам — тем более?
                                                            Безусловно, спорить не с чем.


                                                          3. Атомизированность приводит к props drilling, снижая возможности переиспользования и уменьшая контроль?
                                                            Зависит от того, какая именно атомизированность. Я имел в виду не обертки на каждый div или список, которые действительно сложно переиспользовать ввиду их потенциально громадного количества — для этого уже существуют html-компоненты, которым в props (атрибуты) передаем нужные параметры. А подразумевал я под "сейчас стремятся к большей атомизированности" то, что разбивают код на крупные семантические блоки — Header, Footer, Menu, Table, UsersList. Тысячестрочный компонент, как правило, легко разбить на подобные части, и возможность переиспользования и контроля увеличится.


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

                                                            И в чем проблема? Эти факторы поддержку никак не усложняют.


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

                                                            Нет, это не так. На практике дубляжа никакого не будет и в исходном варианте, зато разбираться в взаимосвязях между мелкими компонентами гораздо сложнее — даже когда декомпозиция проведена грамотно. Затраты на изменения в случае разбивки на мелкие компоненты — выше, поддержка тулинга — хуже. Про случаи, когда декомпозиция неидеальна (а в 90% случаев это будет именно так — иначе бы разбиение не было слишком мелким), я уж вообще молчу.


                                                            Налицо снижение сложности, уменьшение времени на правки, уменьшение количества кода, улучшение производительности (при SCU у чайлдов)

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


                                                            Зависит от того, какая именно атомизированность. Я имел в виду не обертки на каждый div или список

                                                            Ну, я имел ввиду именно это. Это именно то, что на практике наблюдается в современном фронте под соусом использования "лучших практик".
                                                            Разделение же на вещи вроде "Header, Footer, Menu, Table, UsersList" штука вполне понятная и очевидная, но вот прямо сейчас я работаю над проектом, у которого хлебные крошки (хлебные крошки, Карл!) выводятся через 6, ШЕСТЬ, мать его, оберток. В итоге тривиальная задача вида "дописать к крошкам вот в этом месте Х" превращается в полноценное расследование на тему того, какие данные из какой обертки туда приходят и как в эту обертку попадают.
                                                            И когда я это вижу, то, знаете что — пусть лучше будет копипаста и компоненты по тыще строк. Просто потому что по факту с ними работать проще и приятнее, чем с этой вот вермишелью.

                                                        –1
                                                        Лично у меня опыт с React+JSX привёл к тому, что всё смешалось в кучу, и разметка, и логика.

                                                        Так это же проблема не реакта, а проблема в вас, вы не правильно его используете. Но не расстраивайтесь, это повальная проблема для подавляющего числа разработчиков, увы.
                                                        Ведь React это только библиотека для рендеринга DOM дерева.
                                                        Реактовские компоненты должны быть «тупые», логика где изменяются данные от которых зависят те или иные компоненты должна описываться отдельно.
                                                        Идеально для этого подходит связка Typescript + React + MobX, где локальное состояние компонентом и глобальное состояние лежит именно на плечах MobX'a, а не реакта с его this.setState или useState.

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

                                                        Опять же, реакт вообще не про это и не для этого. Тут на помощь идеально приходит MobX.
                                                      0
                                                      In fact, React isn’t even the best React anymore. Preact is a near identical drop-in replacement, using the same API, but greater performance, a much smaller download, and a license that doesn’t need to be signed in the blood of a child.

                                                      Взято из шуточной статьи.

                                                      +2
                                                      Но если бы не холивары по эффективности, отличиям и прочим особенностям инструментов, то возможно двигатель прогресса бы затормозился. Но в любом случае, согласен с вами)
                                                      +3

                                                      спасибо за отличный обзор!

                                                        +2
                                                        Welcome, заходите еще)
                                                        –1

                                                        Проблемы Typescript: строгая типизация, дженерики, сложные типы. Вы это серьезно? Что вообще происходит в ИТ -_-

                                                          +3
                                                          Фраза вырвана из контекста, причем, умышленно удалена фраза «для обывателя».

                                                          Но вернемся к теме. Проводя по 40-50 собеседований в год, на вопросы по TS (так как пишем мы только на нем) слышу: «глубоко не разбирался во всяких дженериках», «не помню, что такое юнион», а встретить человека знающего про тайпгарды — скорее исключение, поэтому да, рынок ИТ весьма перегрет и да, это реалии.

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

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


                                                            О каких обывателях мы говорим? Стажеры и джуны или мимо проходящие курьеры? Базовую идею типов можно за полчаса объяснить водителю такси по дороге на работу. Да и школьники на уроках информатики как-то без особых проблем понимают, что есть строки, а есть целые и дробные числа. Дженерики, юнионы и так далее тоже не рокет саенс. Не нужно курить теорию типов, что уметь этим пользоваться на базовом уровне. Хочется верить, что в индустрии не настолько все плохо...


                                                            Неужели современные начинающие разработчики так страдают и "не могут в типы"? Лично мое мнение, разработчик должен начинать со строгой типизации, а не "коверкать" себе жизнь ее отсутствием. Динамическая типизация это важная фича, но к ней можно "пускать" только окрепшие умы. Хочется верить, что любого джуна можно пересадить с JS на TS за недельку-другую. Зато какой профит для проекта, продукта, компании. А если человек упирается или не может, то нужен ли он такой в команде?

                                                              +1
                                                              На рынке кадров эта профессиональная деформация уже во всю гуляет, к сожалению. Я не против Typescript, ни в коем случае, и в результирующей таблице он в плюсах, а не в минусах и считаю, что все приложения больше to-do листа должны его использовать во избежании дальнейших проблем с рефакторингом, расширением кодовой базы и прочих. Но по моему опыту многие говорят на интервью: «Да, я использую тайпскрипт уже год», но по факту это означает проставить примитивные типы и не более, ну может пару модификаторов методам еще, а это уже звоночек, а нужен ли такой человек, если за год использования инструмента он не поинтересовался даже документацией и не опробовал ее на своем проекте?

                                                              Кастаельно обывателей, да, это джуны, стажеры, но все же изначально стоит им фокусироваться на основах языка, а не на его надстройке/расширении. Всем информация дается по разному, у кого вообще был опыт в языках со строгой типизацией, тут все просто и хорошо, а кому-то и базовые методы массивов даются с трудом. Те, кто толком не освоил JS, могут нырнуть в TS и окончательно потеряться, это мое мнение. Да и многие компании/проекты/команды до сих пор в 2020 году не мигрировали свои базы с JS на TS.

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

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

                                                              Я с удовольствием и распростертыми объятиями встретил бы junior dev с багажом знаний из базовых алгоритмов, статической типизации TS, хорошим нативным JS, возможно знанием фреймворка типа Angular/React/Vue, но зачастую эти люди ожидают позиции middle и более того, они их с 70% вероятностью получат, где-то. И это я говорю про российский рынок, если говорить про европейский, а там я тоже провожу интервью, то ситуация еще хуже, возможно пандемия на это все накладывает свой отпечаток.
                                                          +2
                                                          Хорошо было бы включить в обзор также Квазар — Quasar.dev

                                                          Это такая надстройка над Vue.js со своей экосистемой, кучей стильных компонентов в стандарте Material Design, интернализацией из коробки, а также возможностью сборки приложения как SPA, PWA, SSR, даже десктопных приложений и много чего ещё.

                                                          Считаю, очень заслуживает внимания!
                                                            +1
                                                            Спасибо за информацию по инструменту!
                                                            В данный обзор данный квазар уже точно не попадет, но попробую сделать тест-драйв и в дальнейшем упомянуть в смежных статьях, если такие будут

                                                          Only users with full accounts can post comments. Log in, please.