Вот вот. И вообще лучше использовать спред оператор, тк Object.assign с TypeScript не очень хорошо дружит (можно легко неконтролируемых дел натворить).
поиск — нужно все время нажимать Ctrl + F причем глобально Ctrl + Shift + F
Используйте TypeScript.
не видно сразу от куда ноги растут. Вытекает из пункта выше.
Используйте TypeScript.
нет, это всего мало, так у меня еще весь проект пронизывают константы. Нет я не против констант но зачем? Тем более если их использовать вместе с вложенностью как в примере да если еще их конкатенировать из нескольких то это вообще ад навигации.
Вот ради этого мы вынесли логику отвечающую за передачу данных стору. Reducer остался обеспечивать работу всего механизма. И он должен делать это хорошо не отвлекаясь на вещи его не касающиеся. А нам остается только наблюдать порядок в том от куда растут ноги и если надо то быстро найти и исправить или дополнить.
Очень недальновидно прилепить реализацию ридьюсеров к экшенам:
— В приложении может быть много разных ридьюсеров на тот же самый тип экшена. Допустим я послал экшен из модуля1, а модуль2 и модуль4 будут по-своему его обрабатывать собственными ридьюсерами, плюс lazy модуль5 когда загрузится тоже начнет этот экшен обрабатывать. Пример утрирован, но что-то такое может существовать. Исходите из посыла что экшен это событие с пейлоадом, а ридьюсер это обработчик события. Вы ведь не станете спорить что у события может быть сколько угодно разных обработчиков.
— Представьте себе что у вас больше SPA со множеством lazy/ленивых модулей. Любой экшен может быть послан из любого модуля при этом сами экшены очень легковесны. То есть это не так страшно импортировать допустим все экшены или по отдельности в каждый модуль (особенно если это константы, а не бандлы тк tree shaking). Но вы привязали сам обработчик к экшену и в итоге все модули загрузят и всю логику ридьюсеров тоже что не является желательным поведением приложения.
— Я бы еще причин придумал, но написанного считаю уже достаточно.
Если же говорить о редьюсерах, то ее функционал ничем не отличается от кейса «Выбор редьюсера из объекта по ключу» разобранного в этой статье.
Это не так. В показанном выборе редьюсера из объекта по ключу очень много недостатков которые отсутствуют в unionize подходе:
— unionize поддерживает не только удобное объявление экшенов но и удобную дальнейшую работу с ними (матчинг, фильтеринг и тд)
— Добавить TypeScript типизацию указанному способу так просто не получится потому что объект «оторван» от объявления самих экшенов в которых указаны типы пэйлоадов. Это мега большой недостаток. Нетипизированный JavaScript в наше время вообще вредно использовать для проектов сложнее todo app или hello world.
— Нужно отдельно где-то объявлять и потом отдельно импортировать константы на экшены. Это ведет к неоправданному росту бойлерплейта. В сочетании с отсутствием типизации очень легко сделать ошибку сопоставляя ридьюсер с определенным экшеном. Нетипизированный JavaScript в наше время вообще вредно использовать для проектов сложнее todo app или hello world.
— В случае unionize при матчинге нужно либо опиcать обработчики для всех объявленный экшенов или добавить default обработчик и это подкреплено на уровне TypeScript. Получается что забыть объявить обработчик для экшена не так просто и это хорошо.
Перед выбором unionize я просмотрел множество самых разных библиотек хелперов, хотел свое написать, но unionize оказалась достатоной для моих нужд штукой. Там есть некоторые недостатки, но они решаемы (как например добавление префикса для экшенов).
Чего только не придумают чтобы не использовать простую библиотеку github.com/pelotom/unionize Там вам и бандлы экшенов, и матчеры и другие плюшки, и все при этом хорошо дружит с TypeScript.
Ну так то стор глобальный, можно ведь придумать как не использовать один глабальный. Но в целом какая здесь проблема? Пускай оповещает все компоненты, реагировать логикой будут только те которые должны, остальные просто пропустят сигнал сравнив данные по ссылке что недорого.
Именно один глобальный стор и дает single source of truth бенефит.
Вариантов не много:
— Использовать иммутабельные данные, лучше простых типов (примитивы + объект и массив), тогда можно просто сравнивать по ссылке. Вывод: дешевое сравнение.
— Делать deep checking. Вывод: дорогое сравнение, тормоза.
— Использовать обертку с методами get/set или что-то вроде прокси или Object.defineProperty и внутри творить магию. Вывод: магия, вероятно большее потребление памяти, хакнутая структура данные и тд.
Не использовал unionize, но выглядит не очень читаемо КМК.
Дело не только в читаемости, но в поддежке TS. Есть много аналогов, но именнно эта библиотека сама по себе небольшая, но гибкая. Делать отдельные файлы на каждый экшен это действительно плодить много бойлерплейта. Мне удобнее объединять экшены в unionize бандлы группируя их по назначению. Правда бибиотека пока что не поддеривает префиксы для бандлов, но ее можно форкнуть и добавить.
function onTriggerClick() {this.down('sidebar').toggle()}
Полагаю вызов down ресолвит вложенный компонент и явно вызывает у компонента метод toggle. Но это ведь жесткая привязка к структуре дерева компонентов. Кроме того строгую типизацию такого сделать будет сложновато. Ну и в скорости ресолвинга не уверен.
Листенеры в таком виде не особенно полезны, было бы добно подписаться на изменение определенного участка стора. Можно сделать гибкую штуку на BehaviorSubject из RxJS и кода тоже будет мало не считая конечно саму библиотеку RxJS.
О том что возможности TypeScript совсем не используются писать не буду в деталях, тема широкая. Но в целом использование нетипизированных Object и Function нивелирует практически все преимущества TS, лучше тогда уже просто JS взять.
Правильные компоненты просто не будут реагировать на неревантные сигналы просто сравнив текущие и новые данные по ссылки тк иммутабельный стор это позволяет сделать. Сравнив используя встроенное в мемоизированные селекторы сравнение или в явном виде используя distinctUntilChanged-like подход.
redux в каническом виде я никогда не использовал, преполагаю если следовать каким-то поверхностным гайдам, то бойлерплейта действительно может получиться много. Константы на экшены не нужны, так же как и классы, с помощью github.com/pelotom/unionize можно лаконично описать весь бандл экшенов в одном месте и этот же бандл испольщзовать для матчинга в ридьюсере вместо свичей + поддержка TypeScript (очень помогает контролировать сложность).
Нам нужен сайдбар с одним единственным свойством collapsed.
Бывает нужно например переключать это поле collapsed из самых разных мест или завязать на это же значение еще какие-то отрисовки кроме самого сайдбара и здесь центральный стор помогает очень. Особено удобно когда стор observable.
Ну почему только реакту, это общее понятие. Дропнуть тяжелую операцию много где полезно может быть. В ангуляре тоже для компонентов можно включить «on push» режим и использовать полезность иммутабельности.
Это насущная необходимость при разработке решений сложнее hello world, просто не все это еще осознали.
Это не так, в рантайме они абсолютно идентичны.
А вот как раз python и C# совсем разные.
Используйте TypeScript.
Используйте github.com/pelotom/unionize.
Используйте github.com/pelotom/unionize.
Очень недальновидно прилепить реализацию ридьюсеров к экшенам:
— В приложении может быть много разных ридьюсеров на тот же самый тип экшена. Допустим я послал экшен из модуля1, а модуль2 и модуль4 будут по-своему его обрабатывать собственными ридьюсерами, плюс lazy модуль5 когда загрузится тоже начнет этот экшен обрабатывать. Пример утрирован, но что-то такое может существовать. Исходите из посыла что экшен это событие с пейлоадом, а ридьюсер это обработчик события. Вы ведь не станете спорить что у события может быть сколько угодно разных обработчиков.
— Представьте себе что у вас больше SPA со множеством lazy/ленивых модулей. Любой экшен может быть послан из любого модуля при этом сами экшены очень легковесны. То есть это не так страшно импортировать допустим все экшены или по отдельности в каждый модуль (особенно если это константы, а не бандлы тк tree shaking). Но вы привязали сам обработчик к экшену и в итоге все модули загрузят и всю логику ридьюсеров тоже что не является желательным поведением приложения.
— Я бы еще причин придумал, но написанного считаю уже достаточно.
Это не так. В показанном выборе редьюсера из объекта по ключу очень много недостатков которые отсутствуют в unionize подходе:
— unionize поддерживает не только удобное объявление экшенов но и удобную дальнейшую работу с ними (матчинг, фильтеринг и тд)
— Добавить TypeScript типизацию указанному способу так просто не получится потому что объект «оторван» от объявления самих экшенов в которых указаны типы пэйлоадов. Это мега большой недостаток. Нетипизированный JavaScript в наше время вообще вредно использовать для проектов сложнее todo app или hello world.
— Нужно отдельно где-то объявлять и потом отдельно импортировать константы на экшены. Это ведет к неоправданному росту бойлерплейта. В сочетании с отсутствием типизации очень легко сделать ошибку сопоставляя ридьюсер с определенным экшеном. Нетипизированный JavaScript в наше время вообще вредно использовать для проектов сложнее todo app или hello world.
— В случае unionize при матчинге нужно либо опиcать обработчики для всех объявленный экшенов или добавить default обработчик и это подкреплено на уровне TypeScript. Получается что забыть объявить обработчик для экшена не так просто и это хорошо.
Перед выбором unionize я просмотрел множество самых разных библиотек хелперов, хотел свое написать, но unionize оказалась достатоной для моих нужд штукой. Там есть некоторые недостатки, но они решаемы (как например добавление префикса для экшенов).
Именно один глобальный стор и дает single source of truth бенефит.
— Использовать иммутабельные данные, лучше простых типов (примитивы + объект и массив), тогда можно просто сравнивать по ссылке. Вывод: дешевое сравнение.
— Делать deep checking. Вывод: дорогое сравнение, тормоза.
— Использовать обертку с методами get/set или что-то вроде прокси или Object.defineProperty и внутри творить магию. Вывод: магия, вероятно большее потребление памяти, хакнутая структура данные и тд.
Дело не только в читаемости, но в поддежке TS. Есть много аналогов, но именнно эта библиотека сама по себе небольшая, но гибкая. Делать отдельные файлы на каждый экшен это действительно плодить много бойлерплейта. Мне удобнее объединять экшены в unionize бандлы группируя их по назначению. Правда бибиотека пока что не поддеривает префиксы для бандлов, но ее можно форкнуть и добавить.
Полагаю вызов down ресолвит вложенный компонент и явно вызывает у компонента метод toggle. Но это ведь жесткая привязка к структуре дерева компонентов. Кроме того строгую типизацию такого сделать будет сложновато. Ну и в скорости ресолвинга не уверен.
Листенеры в таком виде не особенно полезны, было бы добно подписаться на изменение определенного участка стора. Можно сделать гибкую штуку на BehaviorSubject из RxJS и кода тоже будет мало не считая конечно саму библиотеку RxJS.
О том что возможности TypeScript совсем не используются писать не буду в деталях, тема широкая. Но в целом использование нетипизированных Object и Function нивелирует практически все преимущества TS, лучше тогда уже просто JS взять.
PS не пишу именно о Redux, но в целом о подходе.
Бывает нужно например переключать это поле collapsed из самых разных мест или завязать на это же значение еще какие-то отрисовки кроме самого сайдбара и здесь центральный стор помогает очень. Особено удобно когда стор observable.