Как стать автором
Обновить

Комментарии 62

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

Если под «глобальный css» подразумевается какой-нибудь styles.css в проекте, в котором прописаны правила под все стили всего проекта, то я бы сказал, что есть бэст практис в программировании — SOLID, у которого аж 2 пункта в нашем случае бьют:
1) Единая ответственность (каждый класс (к примеру) должен отвечать за что-то одно и ни за что другое. В нашем случае — один модуль css должен отвечать за один компонент)
2) Лучше много маленьких модулей, чем один, но унифицированный (отвечающий за кучу всего) — тут думаю, понятно без пояснений.

Не знаю, насколько это притянуто за уши, но СОЛИД распространяется (как я это понимаю) не только на ООП и следовать ему всегда и везде — необязательно (даже где-то противопоказано). Но в совсем простых случаях (как этот, к примеру) можно им руководствоваться, как мне кажется

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

Я бы вас и близко к проекту не подпустил с таким восторженным образом мыслей. Уж простите.
Ну это уже совершенно другой кейс. Никто не запрещает иметь глобальный стиль для коммон правил aka bootstrap)
Понимаю. Допустим, вы хотите добавить компонето-специфичные стили. Конечно же, их следуе хранить рядом с компонентом, и не засорять ими глобальные стили. Это разумно. Но тут у меня возникает другой вопрос: а какого лешего вам понадобились компонето-специфичные стили? Очень уж это, знаете, попахивает костылями, отсутствием понимания дизайн-системы и/или отсутствием в проекте видения стиля.

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

Мой главный поинт: СОЛИД — это хорошо, но руководствоваться нужно в первую очередь здравым смыслом, а уже потом солидом)

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


Или ещё пример: все картинки у вас квадратные (глобальный стиль), но изображение в углу одно (компонент лого, background-image: url), а в середине другое (фото котика).


Бывают стили настолько специфические, что нет смысла сорить ими в глобал.

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

Советую ещё попробовать redux-symbiote, эта библиотека позволяет писать названия экшенов, фабрики экшенов и соответствующие редьюсеры в одном файле, что очень удобно. Я реализовал с нуля один проект как раз на описанном стеке + redux-symbiote, проблем не было.


На всякий случай: название экшена можно получить так:


actions.actionFunc.toString();

А в саге можно написать так:


take(actions.actionFunc, handlerFunc);
Выглядит удобно, пасиб!
Или redux-act
А не пробовали объединять файлы по модулям? Например папка users и уже в ней reducers, sagas и так далее, которые относятся к пользователям.
Вроде звучит неплохо и логично, но как по мне, если я — новый разработчик на проекте, мне куда более привычно видеть папки components, reducers, actions и тд, чем без знаний бизнес-логики проекта лазить по папкам-сущностям. Но это такой себе аргумент в сторону структуры, так что, скорее это вопрос вкуса, нежели какого-то конкретного профита, как я понимаю =)
Это рекомендация разработчиков Redux.
Это Folder-by-feature. Структура, рекомендуемая при разработке больших приложений практически на любом стеке. Используется задолго до появления redux и react.

А где у вас происходит взаимодействие с API? В какой области? Отдельный слой который содержит функцию, которая фетчит, и парсит данные?




PS сорян, уже увидел директорию api

Архитектура, приведенная в статье устарела и довольно неудобная для работы.
1. Используется saga. Работать с ней сомнительное удовольствие. Особых преимуществ перед промисами или thunk она не дает. А кривая обучения жесткая.
2. Создатели Redux уже несколько лет настоятельно рекомендуют группировать логику Redux по фичам.

Сделал за время карантина свой Create React App template с примером рабочего приложения на Redux, тестами и поддержкой SCSS, LESS, PostCSS — github.com/morewings/cra-template-quickstart-redux
А чем те доводы в сторону саг относительно thunk-middleware вас не устроили?
Начнем с того, что я несколько лет работаю на проекте с использованием saga-middleware, senior был тим лидом.

В 90% случаев use case для саги отработать ajax запрос данных с тремя состояниями (PENDING, SUCCESS, FAIL). Использовать для этого сагу — это полный бред и оверинжиниринг.

Ок, рассмотрим более сложный случай — запросы, которые зависят друг от друга. В данном случае у вас есть как минимум три варианта:
1. Написать логику на промисах или thunks. Красиво, идиоматично и понятно. Минус, вы тащите бекэнд логику во фронт.
2. Использовать graphql. Здесь есть хороший separation of concerns. Клиент знает только тип получаемых данных, graphql сервер резолвит данные так как нам надо. Не делаем лишних запросов на бэк. Данные обновляются во всем приложении сразу. Некоторые хипстеры даже используют локальные запросы вместо Redux, прикольно, но на любителя. Минусы, graphql требует изучения и написания значительного количества boilerplate кода. Но в итоге оно окупается.
3. Использовать сагу. Из плюсов разве что на саге можно написать любую извращенную логику. Минусы — никакого separation of concerns, ваш фронт теперь умнее бэка, а работать с ним может только тот чувак, кто пропитчил сагу техлиду. Отладка саги — отдельное удовольствие, погуглите, как оно проглатывает ошибки или рассинхронизируется. Тестирование, см отладка.

В сухом остатке с сагой вы потратите те же усилия, что и на graphql, но в результате получите много эзотерического кода, при этом ваша архитектура так и останется проблемной (салат из бизнес-логики и отображения). Так почему тогда не использовать промисы, которые умеют все то же, что и сага, но за НАМНОГО меньшую цену?

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

А иначе Redux работать не будет. Странное замечание. Все action отдают объект.

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

Видно, ЦРУ автору запрещает нормально thunk писать. Трамп звонит на daily каждое утро и требует: давай пиши их криво, а то в Гуантанамо посажу и подъезд обоссу.
Видимо я забыл в статье упомянуть про то, что thunk для асинхронных экшнов постоянно порождает промис-хелл… Мы делаем экшн для запроса, в котором вызываем другой экшн для следующего запроса, который состоит из еще двух таких же вложенностей — неудобно отлавливать ошибки и выглядит как-то совсем уж неаккуратно, как мне кажется
А непредсказуемые yield'ы повсюду — просто образец аккуратности, да?

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

async/await

Да, если в проекте только простые круд операции, то смысла нет тянуть сагу или другие продвинутые библиотеки, хватит и thunk. Есть множество кейсов где thunk не справляется, например, сокеты, синхронизация между вкладками, throttle и debounce саг и т.д. Саги позволяют элегантно решать проблемы с сайд эффектами.

А что может сага, чего не могут асинхронные функции? С добавлением самописного effect functor хватает вроде для всего. Если есть примеры, делитесь.
Я Redux не использую, но не видел, чтобы в angular, vue или в react с другими менеджерами состояний использовали что-то вроде saga/thunk.
Поэтому у меня вопрос, касательно этого пункта:
Хочется вынести логику запросов и работы с данными для запросов в отдельный модуль — для этого и нужны саги
Это легко делается вообще без каких-либо библиотек. Это redux настолько ущербный, что для нормального вынесения логики работы с данными запросов к нему нужны отдельные библиотеки? Или просто все смотрят, что другие берут thunk и saga и также бездумно тянут их в свой проект? Или же в этих библиотеках что-то есть такого, что делает код проще/лучше, чем код тех, кто redux не использует?
Это redux настолько ущербный

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

Именно, но опять же, садомазо и легко, вещи не совместимые, так что увы))
Ценность комментария была бы больше, если развернуть подробнее слово «убогий» как это видит автор)
Да легко) Вместо тысячи слов просто взгляните на код) Я специально все в одном файле написал, для пущей наглядности. А так, там самый простой и банальный вариант, скажите спасибо что ещё без саг, санок и реселектов всё это написано, а то было бы вообще кошмарно, да и меня бы стошнило быстрее на экран прежде чем я бы дописал пример.

codesandbox.io/s/restless-sound-hvtiw?file=/src/App.tsx — Redux
codesandbox.io/s/hungry-brook-69sb9?file=/src/App.tsx — MobX

Если после этого останутся сомнения в убогости Redux'a, и он вам по прежнему будет нравится, то уж извините)

Как бы getters/setter уже больше 10ти лет, ES6 Proxy 5 лет, а люди до сих пор кроме Redux'a (максимально топорный и примитивный, все делается руками и с тоннами быдло кода) ничего не знают и знать не хотят. Ало, может пора выйти из каменного века, это уже даже не смешно.
Голый redux мало кто использует, есть redux-toolkit.
А как в MobX сделать нормализованный стэйт? Останется преимущество над redux?
Что именно вы вкладываете в понятие нормализованный стейт? Его трактуют по разному. Прямо конкретную ситуацию опишите что должно быть и я покажу как это будет выглядить в MobX'e.
Список сущностей храниться объектом ключем является его id. В redux получается простой селектор state => state.items[id]. В MobX как я понимаю для этого используется MST, но в этом случае теряется преимущество в простоте и количестве кода
Ничего подобного, MST вообще нафиг не нужен, ни при каких случаях, от слова совсем. Если его используют, то уничтожают всю суть. Он создан для тех, кого не покидает redux из души.

Вот:
codesandbox.io/s/keen-snowflake-reg7r?file=/src/App.tsx

Или же вот такой вариант, по красоте с реактивным классом для переиспользования
codesandbox.io/s/interesting-chatelet-k1yq7?file=/src/App.tsx
Тут происходит подписка на весь список, а как сделать чтобы отдельно следить за каждым элементом? Т.е. делаем компонент который рендерит один отдельно взятый элемент и выводим список таких элементов, затем меняем один элемент в списке после чего рендерятся все компоненты (а должен только один, тот который мы изменили)
codesandbox.io/s/keen-snowflake-reg7r?file=/src/App.tsx:1224-1232
Вроде работает как нужно, ререндер только измененных данных
codesandbox.io/s/zen-tharp-eymiv

Ну вот я использую голый реакт и получается даже более удобно чем с mobx, вот пример — https://codesandbox.io/s/competent-engelbart-cltwg. Нет никакой магии геттеров-сеттеров или прокси-объектов, просто вызываем функцию актуализации когда нужно актуализировать view с состоянием. Есть и недостаток в виде менее эффективного обновления (реакт будет делать diff всего приложения при изменении состояния). Но тормоза появляются лишь на больших приложениях (> 10к дом-нод) что встречается нечасто и для 99% mvp-приложений можно обойтись без mobx (и потом можно легко подключить его только в случае появления тормозов diff-механизма реакта).

Даже если для вас getters/setters или proxy это магия, то пусть она и остается магией. Раз уж лень посмотреть и поэксперементировать с getters/setters и proxy, тогда все сразу станет понятым и вся магия улетучится. Какая разница какие именно там потроха, если это работает стабильно и предсказуемо. Я уверен вы не знаете все тонкости и нюансы реакта, однако его вы используете несмотря на другую его магию. Зачем отказываться преднамеренно от крутых фишек из-за спорного аргумента в виде «магии». Тут вам и настоящая полноценная реактивность, минимальное кол-во кода, автоматические подписки/отписки на изменения, оптимизация производительности из коробки и т.д. и т.п.

Просто изменил переменную и всё, любым способом и из любого места. Кому надо, тот отреагирует и перерендерится автоматически без явных вызовов дополнительных. Причем это стало возможно ~10 лет назад, с появлением getters/setters.
Просто изменил переменную и всё, любым способом и из любого места

Это и есть главная проблема MobX. Если Вы работали на хоть сколько то больших проектах, особенно если приходилось бы вникать в код, оставленный в наследство на MobX, Вы бы с уважением отнеслись к Redux.
То, что Вы назвали быдлокодом, всего лишь способ вести проект в строгом соответствии с правилами. Может, TypeScript тоже быдлокод?


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

В ту же кассу. Явное лучше неявного.
Если Вы это оспариваете, то флаг Вам в руки

Или просто все смотрят, что другие берут thunk и saga и также бездумно тянут их в свой проект?

This

А зачем вообще использовать редакс для сетевых запросов?
По моему опыту в 90% случаев это типовые CRUD операции. Которые можно сделать например вот такими либами github.com/tannerlinsley/react-query
Типовой запрос можно и на хуках сделать. Выбор либы — это задел на будущее, на вырост.

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


Если приложение не простейший todo list, вы в первые же дни столкнётесь с кучей подводных камней, которые не решаются своими хуками на фетчах.


+1 за react-query с первого дня.

Можно в контекст прокинуть. Но вы правы, в итоге Redux получится.

Шел 2020 год, а люди до сих пор не знают что такое MobX и продолжают использовать допотопные, примитивные и ущербные технологии в виде redux и прочей ереси типо санок, саг, реселектов и тому подобное. 2014 год так и не хотите искоренять из себя. Больно смотреть на общий уровень разработки конечно.

Redux-saga-reselect, максимально переиспользуемые компоненты, бесконечные контейнеры-обертки, короче ясно-понятно путешественник из 2016))

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

В статье описал, но может быть не так наглядно. Нужно это для того, чтобы при изменении/расширении объекта в сторе нам не пришлось лазить по всем контейнерам, обращающимся к этому куску стора. Мы залезаем в селектор (максимум в парочку селекторов) и меняем путь до пропса там один раз =)
Грубо говоря, есть у нас 5 контейнеров, которые вытаскивают что-то + state.users.data[index].name

Бэк поменял логику и вместо name нам теперь приходит поле с наименованием title. Нам придется лезть во все 5 контейнеров и менять там это имя — не круто. А с селектором так делать не придется — поменял один-два селектора и радуешься жизни

Это как записывать строки в константы, как бы
все равно не допонимаю, зачем именно мемоизировать? Я не говорю, что нужно отказываться от createSelector, но использовать его стоит только в том случае, если функция, переданная в него создает новые данные с новыми ссылками. Для простых случаев (обычное получение пропросов стора) можно же сделать так же, но на функциях:
const getUsers = (state) => state.users
const getUser = (state, index) => getUsers(state).data[index]
const getUserName = (state, index) => getUser(state, index).name


Я так понимаю, смысл в том, чтобы в последней функции поменять name, на title, например. Все что будет приходить в контейнеры не поменяется.
Не переименуете в 5 местах — увеличите разрыв между фронтом и бэком. Будут на бэке везде title а на фронте везде name. И попробуй разберись потом что откуда взялось. Терминологию лучше поддерживать в синхронизации.
Шел 2020 год, а люди до сих пор не знают что такое MobX и продолжают использовать допотопные, примитивные и ущербные технологии в виде redux и прочей ереси типо санок, саг, реселектов и тому подобное. 2014 год так и не хотите искоренять из себя. Больно смотреть на общий уровень разработки конечно.

на дворе 2020 а люди переизобретают Backbone и Marionette из 2012 :)

Что правда чтоли??)))) Явный pub/sub руками да? .on .off. trigger и т.п да? Вы знаете что такое getters/setters и proxy? Когда они появились в js и что с их помощью можно делать?)
Очевидно, что то, что вы перечислили выше вы узнали недавно и естественно эволюцию менеджеров состояний пропустили и не понимаете их вектор развития.
Рекомендую ознакомиться для начала с Backbone и Marionette и после почитать манифест reflux, чтобы иметь представление как развивалась индустрия и от чего уходила и к чему пришла.
Ага, разумеется))) нету никакого вектора развития стейт менеджеров. Начиная с es6 и по сей день proxy это предел совершенства и возможностей js. А в целом они все pub/sub, и делятся на примитивные и ущербные как redux и ему подобные с ручной подпиской и иммутабильностью или же современные, использующие возможности JS на 100%, такие как mobx и ему подобные реактивные, с автоматической подпиской, которые используют getters/setters и/или proxy, тот же vue например.
А вообще я не понял, мне показалось что вы на мой комментарий ответили по поводу mobx, а щас присмотрелся, оказывается не на мой
Есть же отличная штука redux-toolkit, там и удобное создание редюсеров/экшенов и нормализация и селекторы из коробки. Мне кажется это лучшее, что изобрели для редакса.

Я примерно тоже к такому же пришел. Саги невероятно удобная вещь. Она легко читается и контролируется. Единственный минус это то что при таком подходе оочень долго пишешь, но она окупается в долгосрочной перспективе. Еще приплюсуй typescript и вообще будет смак

Эх, сколько вам ещё только предстоит открыть на своем пути, раз в 2020 году вы считаете саги удобными)) Нас уже в 2015 году тошнило от саг и санок и прочей ереси, а вы их только в 2020 открыли) Оглянитесь по сторонам, так вообще офигеете от того что есть и как оказывается можно на настоящему крутой и понятный код писать, а не саги, санки и вот это вот всё из прошлого века)

В 2010 году нам дали getters/setter и всё, с тех пор можно писать и использовать по настоящему крутые стейт менеджеры с автоматической подпиской/отпиской и автоматическим вызове реакций на изменения, в 2016 году нам дали ES6 Proxy, так это вообще просто бомбически и ограничения которые были в getters/setters исчезли и жить стало ещё лучше, но нет же, это не наш путь, наш путь это мазохизм, допотопные и топорные «технологии», где все надо делать ручкам и писать при этом тонны однообразного быдло кода, который автоматически сразу же устаревает и подлежит переписыванию с нуля.

Хотя может быть я чего-то не понимаю и писать код в 2020 году так же, как его писали в 2014 году это круто.
Поясните мне может я отстал от жизни что вместо санок использовать? что нынче модно у молодежи?
React + MobX.
И тут дело не в моде, а в здравом смысле и в колосальном удобстве, я использую MobX с начала 2016 года. Так что это не какая-то новая фигня, ради новой фигни.

Вот примеры быстро взглянуть и оценить суть:
codesandbox.io/s/restless-sound-hvtiw?file=/src/App.tsx — Redux
codesandbox.io/s/hungry-brook-69sb9?file=/src/App.tsx — MobX

Тут расширенный набор всяких штук
codesandbox.io/s/suspicious-water-5wwnz
Годно. Пока не использовал MobX в проде. Поэтому не буду холиварить. Думаю что на каждый проект все индивидуально. Это везде так. Допустим на ладе калине нет смысла устанавливать движок боинга)
В том то и прикол, что MobX это не оверинженеринг и какая-то абская и громоздкая штука, он простой, минималистичный и полностью заменяет управление состояние в React'e. React становится чисто view, вся логика уже в глобальных и локальных состояниях компонентов. Его можно смело использовать абсолютно в любом проекте и получать удовольствие.
Нету ни одного кейса в котором Redux или голый React(кроме тупой верстки полностью без логики и состояния) был бы лучше чем MobX, ну реально ни одного.
Я не спорю. Оба молотка хорошие. Вопрос в том каков плотник и какая задача стоит
Увы нет. Только один молоток хороший, второй годится только пальцы ломать, а не гвозди забивать.
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.