Comments 41
Выглядит очень увлекательно. А чего демку куда-нибудь не выложили, чтобы можно было руками пощупать что получилось?
Модули не зависимы друг от друга. Модификация любого модуля не влияет на работу других модулей. Допускается зависимость модулей от «ядра» системы.Это неизбежно приводит к распуханию ядра от всякой никак не связанной с ним фигни. Или вы смогли как-то это решить?
В итоге в ядре есть ограниченный набор компонентов, который широко используется в рамках приложения. Если где-то надо нарисовать графики, или что-то еще сделать из области rich ui, то такой модуль будет использовать свои компоненты и они скорее всего будут сложно поддаваться повторному использованию, т.е. выносить их в ядро — не нужно.
Если нужно сделать 2 примерно одинаковых модуля, но один — с перламутровыми пуговицами, используется техника
copy/paste
. Да, если захочется изменить оба модуля, то придется в два раза больше исправлять, но эта а) эту работу можно дать двум разработчикам, а не одному, б) если модули были чуть-чуть разными, то при модификации с большой вероятностью они разъедутся со всеми вытекающими из «хрупкого базового класса».Чтобы ядро не «распухало» для UI нужно выбирать какие-то пакеты компонентов и ставить через npm.
А в чём проблема повторного использования графиков и прочего rich ui?
Ну и опять же, с какой стати App должен знать о связи Dashboard -> Widget?
Это просто палка о двух концах, все хорошо делится на модули до появления первого связующего модуля, а потом начинаются пляски вокруг Core/Shared/<как_угодно>.
Edit: ну, dashboard — один из многих разделов большого App, сунуть его туда целиком нельзя.
const Profile = default (props) => (<h2>Привет, {props.name}</h2>)
Никогда раньше такого не видел, зачем тут default?
Про onEnter, получите и распишитесь. :)
v4 is a complete rewrite. As such, there is no singular breaking change. We have some similar-looking things (<Route path="/foo" component={Foo} />
), but the behaviors are completely different. You should expect none of your existing react-router usage to work under 4.0.
As for the on* hooks, they were removed because they already exist in React as the lifecycle methods. We were reimplementing them inside the Router, but they didn't exactly behave like they should. So, why provide an inferior or conflicting API? Everything is way more React-y now, and it's way better as a result. You no longer have to mix paradigms or code for two different systems. It's just React now. It's a much lower cognitive load.
And for "plain routes", we've extracted that to a separate package: https://github.com/ReactTraining/react-router/tree/master/packages/react-router-config You can see the reasoning for this here:
The approach being taken for 4.0 is to strip out all the "batteries included" kind of features and get back to just basic routing. If you need query string parsing or async loading or Redux integration or something else very specific, then you can add that in with a library specifically for your use case. Less cruft is packed in that you don't need and you can customize things to your specific preferences and needs.
Что внутри не так и важно, лишь бы работал.
Мне лично более симпатичен подход, когда в команде есть несколько спецов, которые пишут инструмент, а остальные его применяют. Но здесь требуется более тесное взаимодействие.
Это не критика, наверняка у вас все продумано. Так, рассуждения.
Есть вопрос по поводу redux: какой смысл использовать mapStateToProps? Умный контейнер прекрасно передает глупым компонентам свое состояние и каллбэки, setState вызывает цепочку рендеров. Реализация через редюсеры — это еще один уровень сложности. Зачем?
Я понимаю, когда нужно отправить команду на самый верх, чтобы она сверху вниз взбодрила кого надо, но в отношении родитель/дети redux лишний (имхо). Простое лучше сложного.
Спасибо.
Мне лично более симпатичен подход, когда в команде есть несколько спецов, которые пишут инструмент, а остальные его применяют. Но здесь требуется более тесное взаимодействие.
У нас «инструмент» — это ядро. Ядро пишут несколько человек. Остальная команда в основном использует. По примеру специалист еще не знакомый со стеком, может реализовать простой модуль не вникая в то, что под капотом. Более сложные модули требуют более высокой квалификации.
Есть вопрос по поводу redux: какой смысл использовать mapStateToProps? Умный контейнер прекрасно передает глупым компонентам свое состояние и каллбэки, setState вызывает цепочку рендеров. Реализация через редюсеры — это еще один уровень сложности. Зачем?
Я понимаю, когда нужно отправить команду на самый верх, чтобы она сверху вниз взбодрила кого надо, но в отношении родитель/дети redux лишний (имхо).
Эту часть не вполне понял :) Может привести пример?
Пока, скажем так, адекватного решения проблемы нет
Чудесно. Для сравнения:
- Открываем: http://mol.js.org/#demo=mol_app
- Открываем консоль и включаем эмуляцию GPRS на вкладке Network для наглядности.
- Вручную меняем локаль на английскую:
$mol_locale.lang( 'en' )
- Во всех блоках, где выводились локализованные строки включился индикатор загрузки.
- Через какое-то время все русские тексты поменялись на английские.
И для этого не пришлось вообще ничего специально делать. Достаточно просто получить текст таким образом: $mol_locale.text( [ '$mol_app_demo' ] , 'title' )
Я почти уверен, что mol прекрасен. Больше того, может озолотить (когда-то меня приняли без экзаменов в Мамбу, как опытного спеца по велосипеду OnPHP). Но пока буду дальше жевать кактус по имени React. :)
Вердикт: вместо того, чтобы распыляться тут в комментариях, пишите больше статей в ключе практического применения своего решения.
Но, елки палки, сделайте нормальные selling туториалы с описанием как решать стандартные наболевшие проблемы.
У меня всего 2 руки и нет единомышленников. Туториалы я пишу по мере возможности. Но думаю дело пошло бы быстрее, если бы вы озвучили с какими конкретно трудностями столкнулись, чтобы я раскрыл эту тему подробнее.
Роутинг: https://github.com/eigenmethod/mol/tree/master/state/arg
сайд эффекты — тут что имеется ввиду?
композиция компонентов, переиспользование компонентов: https://github.com/eigenmethod/mol/tree/master/view
Ну а пока вы ужинаете, немного аналитики...
Итак, выводим семьсот с мелочью круглячков в форме треугольника серпинского, каждый из которых раз в секунду меняет содержимое, а всё целиком ресайзится каждый фрейм.
React
Реакту становится очень плохо, так как его архитектура заставляет его делать кучу лишней работы каждый фрейм.
React Fiber
Лишняя работа никуда не делась, но теперь она равномерно размазана по фреймам. При этом если пользователь начинает возюкать над круглечками, то обновление их содержимого замирает.
$mol
Так как архитектура ориентирована на минимизацию лишних вычислений, то даже без "квантификации рендеринга" мы более чем укладываемся во фрейм. Разве что раз в секунду происходит дроп одного фрейма из-за массового обновления содержимого всех узлов, но это не заметно для пользователя. На возюканье мышью реагирует быстро и обновление содержимого круглячков не останавливается.
Я даже пробовал прикрутить "квантификацию", причём не только рендеринга, но и вообще всех вычислений, чтобы анимации не подтупливали, когда рендерится что-то огромное, но это приводило к общему замедлению рендеринга (квантификация не бесплатна) и глюкам типа как у react fiber, когда возюкаешь мышью и часть страницы замирает. В результате вернулся всё же на вариант с полным обновлением за раз.
Не такие уж они и разные на самом деле. Вообще, кейс не мой, а написан для демонстрации преимуществ react fiber перед react: https://github.com/claudiopro/react-fiber-vs-stack-demo На всяких конференциях только его и показывают.
Выложил реализацию на $mol, кому интересно: https://nin-jin.github.io/react-fiber-vs-stack-demo/
Пример: есть панель со списком вложений. Рядом с именем файла крестик (удалить). Передать компонентам нужно свойство readOnly, контейнерную функцию (clickOnKrestik) и что-то статичное. Зачем здесь redux?
Я не против сторе, я против того, чтобы делать ВСЕ на редюсерах.
Задача: нужно сделать 6 панелей с однотипными компонентами и наваять из них около 20 форм для работы с БД. Связь родитель/ребенок, все просто и понятно, никаких mapDispatchToProps и mapStateToProps.
SPA вовсе не означает, что все должно быть на одной странице в одном контейнере.
Повсеместно применяю функциональные (stateless) компоненты. Изобрел вот такой велосипед:
export const pureComponent = (fn) => {
class Wrapper extends React.PureComponent {
render() {
return fn(this.props, this.context)
}
}
// не надо, т.к. подписывает на контекст как и функциональный компонент,
// так и оболочку-PureComponent; лучше назначать сразу оболочке (снаружи)
// Wrapper.contextTypes = fn.contextTypes
Wrapper.displayName = fn.name
return Wrapper
}
И теперь нужно следить только за props-ами.
Ещё разглядывал сегодня redux-persist, например. Для PWA сгодится.
Архитектура модульных React + Redux приложений