Справедливости ради хочу отметить, что даже по кнопкам 200х200 можно легко промахнуться, а расстояние в этом деле и скорость прицеливания играют немаловажные роли, и пренебрегать ими не стоит даже в грубых спорах об отступах, как исключительно эстетической составляющей интерфейса. :-Р
Если так посудить, то это не функциональный дизайн, а опять инженерное решение. Раньше перед инженером задача была ускорить заточку большим инструментов (сделали круглый камень и раб крутит ручку), а теперь стоит задача удешевить работу (избавиться от лишнего рта). И тут появляется ножной привод, теперь нужен только один рабочий.
И если так судить, то дизайнеру в этом мире нет места. Или, быть может, хороший дизайнер это и есть инженер?
P.S.
Говоря про хорошего дизайнера, я имею ввиду именно проектировщика системы, который решает определенную задачу, а не художника-оформителя, который лишь выбирает в какой цвет покрасить станок.
Чтобы не включать всюду реакт вебпаку в конфигурации можно указать externals.
В целом же, по-моему, затея сомнительная и не понятно как решить какие данные ему скормить (в примере только текущая дата).
Интересно узнать какая за этим бизнес-задача стояла :)
Если я не ошибаюсь — вы потеряли someData к моменту манипуляции с данными.
А вот вариант с Promise.all — в данном случае лучший, если только второй запрос не требует информации из первого :)
Если копнуть поглубже в концепции и особенности реакта с редуксом, то вы заметите, что там есть некоторые особенности. И, как мне кажется, чтобы в головах разработчиков не возникало лишней путаницы и были данны различные наименования.
Например:
Действия (аналог событий) — главное отличие от привычных нам событий, что на них нельзя подписываться для изменений данных в стейте (модели), их можно только вызывать. Но есть всякие штуки типа redux-saga, которые позволяют создавать подписки для получения неких сайд-эффектов, но это другая песня и делать это нужно осторожно.
Редюсеры (аналог моделей) — все модельки упаковываются в один стор. Главная особенность, что никто напрямую не дергает модельку, а каждая моделька сама применяет к себе действия (события) и, возможно, в следствии меняется. И стор всегда возвращает консистетное состояние всей системы (всех моделей).
Контейнеры (statefull components) (аналог контроллеров) не должен выполнять какой-то логики обработки данных, он должен ее лишь получать и назначать вьюхе (все как в правильном активном MVC). И привязывать вызов экшенов (! но не решать какую модельку когда потрогать и как). И каждый такой контейнер может работать сразу с множеством «моделей» (получать любые данные из стора), хотя привычные всем контроллеры чаще всего работают с одной моделькой. А в связке с редуксом и вовсе многие рекомендуют делать их тоже стейтлесс и все стейты хранить в общем стейте — это снимает множество боли.
Компоненты — да, привычные всем тупые вьюхи.
Отсюда следует вывод, что называть это MVC не верно, т.к. оно имеет ряд концептуальных отличий и одно из самых жирных — отсутствие pub/sub. (с тем же успехом можно MVP и MVVM называть MVC)
Не подумайте что я ярый фанат реакта, но из всех ангуляров и бекбонов он мне доставляет меньше всего боли при разработке сложных приложений (вспоминается цитата из выступления Александра Соловьева про FRP и кложуру «У меня уже все болит от этих чик-чик»). Но я все чаще смотрю в сторону FRP библиотек и языков.
… и передаете тип вызываемого редьюсера. Чтобы вызвать 3 редьюсера придется сделать 3 диспатча.
Это утверждение не верно. В Redux есть экшены, которые изначально являются простыми объектами с определенной структурой (Flux Standart Actions), который содержит в том числе тип экшена. Тип же это любая строка, циферка или что угодно, с чем мы сможем потом сравнить (а чтобы избежать ошибок — их выносят в отдельный файлик констант). И есть редюсеры, которые комбинируются с помощью combineReducers. То есть фактически редюсер всегд один, но может состоять из подмножества небольших редюсеров.
Что происходит во время диспатча — экшен прокидывается в этот самый единственный редюсер, а тот в свою очередь прокидывает экшен внутрь всех дочерних, каждый вовзвращает свой кусочек стейта и в итоге мы получаем новый стейт.
То есть, если не связывать тайпы с редюсерами, а чтобы тайп был фактом действия (как это рекомендует сам Дэн Абрамов), то получится что экшентайпы будут выглядеть, например, так:
COUNTER_TICK
API_REQUEST
MESSAGE_SENDED
MESSAGE_READED
и т.д.
При этом любой редюсер может реагировать на любой из экшенов. В примерах Redux-а это делается с помощью switch(action.type) {… } внутри любого из них.
Это я понял.
Но в вашем примере получается, что все эти три компонента — прогрессбар, ошибка и данные юзера связаны между собой (смотрят в один кусок стейта). То есть их независимость, о которой я говорил, теряется.
В моем же примере ошибки могут приходить из любых других асинхронных запросов или даже вполне себе синхронных, например, форма не прошла валидацию, аналогично и с прогрессбаром.
И конечно же тут на самом деле будут константы вместо магических экшн-тайпов и урлов :)
А компоненты, соответственно получают эти кусочки стейтов (с помощью селекторов / курсоров выдергивают только свои) и:
формочка показывает ошибки, если они есть или закрывается если есть юзердата
прогрессбар в данном случае просто крутилка, которая отображается пока длина массива больше 0
ошибки показываются, если есть что показать (в данном примере без удаления и проверок на актуальность)
На самом деле этот пример — упрощенный кейс из моей практики в текущем проекте, и он касался не логина. Но, если это поможет, то оформлю его в виде кода, максимально упростив (без проверок, иммутабельных состояний и прочих вещей, которые должны присутствовать) и, чтобы не углубляться в реализацию асинхронных запросов, заменю запрос экшеном с использованием redux-thunk, который делает диспатч FSA и второй диспатч по таймауту.
Давайте представим, что у нас есть несколько компонент: один предоставляет юзеру возможность логиниться, второй показывает прогрессбар, третий отображает ошибки. И чтобы они никак не были связаны между собой — каждый следит только за своим кусочком стейта. То есть предполагается, что ошибки и процессы могут быть из кучи других мест.
И вот юзер вводит логин-пароль, вызываем экшен API_REQUEST, который шлет запрос через какую-нибудь миддлварь —> компонент процесса показывает прогрессбар —> приходит ответ сервера с ошибкой авторизации —> Прогрессбар пропадает —> ошибка висит в углу пока ее не скроют или она не перестанет быть актуальной —> у формочки логина тоже отображается ошибка.
Если у нас отделены редюсеры от экшенов, то это легко реализовать, подписав каждый редюсер на нужные нам экшены: редюсер юзера (из стейта которого берет данные об ошибках формочка) ждет юзердату / ошибку в API_RESPONSE, прогрессбар положил в стейт данные на API_REQUEST и убрал их на API_RESPONSE, а редюсер ошибок положил ошибку, получив ее в API_RESPONSE.
Итого у нас три несвязанных компонента со своими стейтами и своей логикой, которые фактически слушают одни и те же события: два экшена.
В вашем же случае, как я понимаю, придется создать для каждого компонента отдельные экшено-редюсеры и явно комбинировать их в «мега экшене» (типа doMultipleActions). И мне почему-то кажется что в редкс-девтулз мы увидим, как задиспатчился этот самый «мега экшен», а тот в свою очередь задиспатчил еще несколько. Т.е. мы получаем более сложную хистори, которую в случае чего будет сложнее откатывать (если речь пойдет не про логин, а скажем про редактирование чего-нибудь с возможностью у юзера сделать анду).
Надеюсь я понятно изложил пример. Если я не прав, то поправьте меня. Спасибо.
Справедливости ради хочу отметить, что даже по кнопкам 200х200 можно легко промахнуться, а расстояние в этом деле и скорость прицеливания играют немаловажные роли, и пренебрегать ими не стоит даже в грубых спорах об отступах, как исключительно эстетической составляющей интерфейса. :-Р
И если так судить, то дизайнеру в этом мире нет места. Или, быть может, хороший дизайнер это и есть инженер?
P.S.
Говоря про хорошего дизайнера, я имею ввиду именно проектировщика системы, который решает определенную задачу, а не художника-оформителя, который лишь выбирает в какой цвет покрасить станок.
Чтобы не включать всюду реакт вебпаку в конфигурации можно указать externals.
В целом же, по-моему, затея сомнительная и не понятно как решить какие данные ему скормить (в примере только текущая дата).
Интересно узнать какая за этим бизнес-задача стояла :)
А вот вариант с Promise.all — в данном случае лучший, если только второй запрос не требует информации из первого :)
Например:
Действия (аналог событий) — главное отличие от привычных нам событий, что на них нельзя подписываться для изменений данных в стейте (модели), их можно только вызывать. Но есть всякие штуки типа redux-saga, которые позволяют создавать подписки для получения неких сайд-эффектов, но это другая песня и делать это нужно осторожно.
Редюсеры (аналог моделей) — все модельки упаковываются в один стор. Главная особенность, что никто напрямую не дергает модельку, а каждая моделька сама применяет к себе действия (события) и, возможно, в следствии меняется. И стор всегда возвращает консистетное состояние всей системы (всех моделей).
Контейнеры (statefull components) (аналог контроллеров) не должен выполнять какой-то логики обработки данных, он должен ее лишь получать и назначать вьюхе (все как в правильном активном MVC). И привязывать вызов экшенов (! но не решать какую модельку когда потрогать и как). И каждый такой контейнер может работать сразу с множеством «моделей» (получать любые данные из стора), хотя привычные всем контроллеры чаще всего работают с одной моделькой. А в связке с редуксом и вовсе многие рекомендуют делать их тоже стейтлесс и все стейты хранить в общем стейте — это снимает множество боли.
Компоненты — да, привычные всем тупые вьюхи.
Отсюда следует вывод, что называть это MVC не верно, т.к. оно имеет ряд концептуальных отличий и одно из самых жирных — отсутствие pub/sub. (с тем же успехом можно MVP и MVVM называть MVC)
Не подумайте что я ярый фанат реакта, но из всех ангуляров и бекбонов он мне доставляет меньше всего боли при разработке сложных приложений (вспоминается цитата из выступления Александра Соловьева про FRP и кложуру «У меня уже все болит от этих чик-чик»). Но я все чаще смотрю в сторону FRP библиотек и языков.
Это утверждение не верно. В Redux есть экшены, которые изначально являются простыми объектами с определенной структурой (Flux Standart Actions), который содержит в том числе тип экшена. Тип же это любая строка, циферка или что угодно, с чем мы сможем потом сравнить (а чтобы избежать ошибок — их выносят в отдельный файлик констант). И есть редюсеры, которые комбинируются с помощью combineReducers. То есть фактически редюсер всегд один, но может состоять из подмножества небольших редюсеров.
Что происходит во время диспатча — экшен прокидывается в этот самый единственный редюсер, а тот в свою очередь прокидывает экшен внутрь всех дочерних, каждый вовзвращает свой кусочек стейта и в итоге мы получаем новый стейт.
То есть, если не связывать тайпы с редюсерами, а чтобы тайп был фактом действия (как это рекомендует сам Дэн Абрамов), то получится что экшентайпы будут выглядеть, например, так:
COUNTER_TICK
API_REQUEST
MESSAGE_SENDED
MESSAGE_READED
и т.д.
При этом любой редюсер может реагировать на любой из экшенов. В примерах Redux-а это делается с помощью switch(action.type) {… } внутри любого из них.
Но в вашем примере получается, что все эти три компонента — прогрессбар, ошибка и данные юзера связаны между собой (смотрят в один кусок стейта). То есть их независимость, о которой я говорил, теряется.
В моем же примере ошибки могут приходить из любых других асинхронных запросов или даже вполне себе синхронных, например, форма не прошла валидацию, аналогично и с прогрессбаром.
п.с.
Минусы не мои :)
А компоненты, соответственно получают эти кусочки стейтов (с помощью селекторов / курсоров выдергивают только свои) и:
Давайте представим, что у нас есть несколько компонент: один предоставляет юзеру возможность логиниться, второй показывает прогрессбар, третий отображает ошибки. И чтобы они никак не были связаны между собой — каждый следит только за своим кусочком стейта. То есть предполагается, что ошибки и процессы могут быть из кучи других мест.
И вот юзер вводит логин-пароль, вызываем экшен API_REQUEST, который шлет запрос через какую-нибудь миддлварь —> компонент процесса показывает прогрессбар —> приходит ответ сервера с ошибкой авторизации —> Прогрессбар пропадает —> ошибка висит в углу пока ее не скроют или она не перестанет быть актуальной —> у формочки логина тоже отображается ошибка.
Если у нас отделены редюсеры от экшенов, то это легко реализовать, подписав каждый редюсер на нужные нам экшены: редюсер юзера (из стейта которого берет данные об ошибках формочка) ждет юзердату / ошибку в API_RESPONSE, прогрессбар положил в стейт данные на API_REQUEST и убрал их на API_RESPONSE, а редюсер ошибок положил ошибку, получив ее в API_RESPONSE.
Итого у нас три несвязанных компонента со своими стейтами и своей логикой, которые фактически слушают одни и те же события: два экшена.
В вашем же случае, как я понимаю, придется создать для каждого компонента отдельные экшено-редюсеры и явно комбинировать их в «мега экшене» (типа doMultipleActions). И мне почему-то кажется что в редкс-девтулз мы увидим, как задиспатчился этот самый «мега экшен», а тот в свою очередь задиспатчил еще несколько. Т.е. мы получаем более сложную хистори, которую в случае чего будет сложнее откатывать (если речь пойдет не про логин, а скажем про редактирование чего-нибудь с возможностью у юзера сделать анду).
Надеюсь я понятно изложил пример. Если я не прав, то поправьте меня. Спасибо.