Pull to refresh

Comments 113

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

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

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

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


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


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

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

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

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

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

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

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

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

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

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


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

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

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

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

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


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

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


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

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


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

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

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


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


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

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


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

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


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

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

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

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

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

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

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

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

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

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


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

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


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

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

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

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

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. И тут ответ — потому что таким образом мы или нагружаем компонент логикой или, по крайней мере, обязываем разбираться в специфике обработки коллбэков. Что повышает связность.
Вот поэтому и тянет махнуть рукой на 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
Вокруг реакта есть куча старых и новых надстроек и библиотек и какие в каком виде применять для меня как для новичка во фронтенде — загадка

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

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

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

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

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

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


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


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


JustDont


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

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

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

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

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

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


Delphin92


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

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


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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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


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


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

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


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

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


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

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


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

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


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

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


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

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


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

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


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

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


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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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


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

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


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

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


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

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


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


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

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


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

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


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


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

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


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

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


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

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


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

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


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

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


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

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


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

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

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

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

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

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

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

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

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


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


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

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

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

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

Хах, ну тут вообще фиаско.
Вот это не очевидно и как-то не явно? Прям вот вообще не понятно откуда что импортируется, да? Что там есть вообще? Что делает да?
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 года, в реакте все компоненты тупые и должны быть только тупыми. Они зависят только от состояния приложения и внутреннего состояния самих компонентов. А это состояние разумеется должно управляться не реактом, т.к. оно убогое. А другим инструментом.
Вообще всё так не явно, не понятно и запутанно. А главное сложно и поддерживать не возможно.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

С чего вы это взяли? Ещё как будут, проверено на практике неоднократно, как мной, так и моих друзей программистов начиная с 2016 года.
Кому покайфу утопать в говнокоде redux подхода?
Правильно, никому кроме мазахистов конечно.
Поэтому с удовольствием все переписывают на MobX.
Но опять же, если вас собеседует команда мазахистов, а вы таковым не являетесь, то врятли вам стоит соглашаться на работу с ними. Но это конечно ваше личное дело. Но это не мой выбор.
Есть ещё вторая каста мазахистов, которые считают что голый react вообще лучше чем react + стейт менеджер. Это тоже те ещё кадры конечно.
Если Вы приходите как лоурейтовый фрилансер — на такого ориентироваться не станут ))
Да и на временной работе Вам не все ли равно? Оплата-то от этого не зависит
Не сочтите за наглость, но как в такой архитектуре сделать асинхронные запросы и изменить сторедж до рендеринга, то есть в async componentDidMount()? Всякие хаки вроде
const s = this.context.redux.getState()
const dispatch = this.context.store.dispatch

просто так работать внутри componentDidMount не хотят, что нужно приконнектить из разговора умных людей не понял, да и думаю с 2015 оно устарело.
Вся соль в реализации с 83 строки
Махните снова в какую сторону копать, плиз.
Я не очень понял проблему. Почему не пойти обычным путем, приконнектить редакс к компоненту и обращаться через пропсы? Возможно, есть какие-то подводные камни, о которых я не знаю, поскольку редко работаю с классовыми компонентами.

Я так понял, вам надо инициализировать стейт асинхронными данными перед началом работы приложения? Я обычно это делаю примерно следующим образом:

const App = ({loadingState, initializeData}) => {
    useEffect(() => {initializeData()}, []);

    return (
        loadingState === 'loading' ?
            <Spinner/>
        : loadingState === 'loaded' ?
            <Layout/>
        :
            <Forbidden/>
    );
};

export default connect(
    state => ({loadingState: state.loadingState}),
    {initializeData}
)(App);


В данном случае initializeData — redux-thunk-овский экшн примерно следующего вида:

export const initializeData = () => async dispatch => {
    try {
        const {data} = await api.loadData();
        dispatch(setLoadingState('loaded'));
        dispatch(setData(data));
    } catch {
        dispatch(setLoadingState('forbidden'));
    }
};


Надеюсь, что помог :)
Да, большое спасибо!
Прибывал ведь useEffect в начале изучения React, потом вылетело из головы, что его можно так использовать, и предзагрузка изображений ведь в нем работает
city_img.forEach((picture) => {
    const img = new Image()
    img.src = picture
})
выходит, классовые компоненты и не нужны за ненадобностью хуков и чего только на собеседованиях про них спрашивают…
Видимо, осталось только научится верстать с bootstrap, чтобы нормально найти работу ;)
P.S. показалось — PageSpeed Insights все равно просит перезагрузить картинки, хотя, видимо к реакту это уже имеет мало отношения
Предвосхищая вопросы — mobx я пробовал, не понравилось.

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

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

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

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

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

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

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

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

А просто языком молоть, это всё что угодно можно говорить. Всё должно подтверждаться экспериментами, в нашем случае кодом)

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


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 то получится вообще красиво.

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

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

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

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

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


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

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

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

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

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


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


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

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

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

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

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

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


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

Каждый выбирает, что ему по душе, мне принцип фриланса ближе, а то что подходы неэффективные — так кто платит тот и заказывает музыку :)
Хотя Redux действительно ужасен.
Не могу не спросить — складывается ощущение, что bootstrap сложнее самого sass/css: если например нужно сделать кнопку определенного стиля в определенном состоянии другого цвета и размера не через костыли вроде !important, а через стандартную кастомизацию.
Со мной все плохо?
Просто
div {
  width: 100px;
  height: 100px;
  position: relative;
  background-color: red;
  animation-name: example;
  animation-duration: 4s;
  animation-iteration-count: 3;
}
кажется проще, чем искать всякие
@each $color, $value in $theme-colors {
  .btn-#{$color} {
    @include button-variant($value, $value);
  }
}
в коде или документации и догадываться какие есть theme-colors и где что-нибудь прописать, чтобы оно чем-то не переопределялось и не развалить что-то другое в неожиданном месте.
P.S. писал на эмоциях — все не так уж страшно в бутстрапе, но мысль о том можно ли на нем реализовать любой макет не отпускает.

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


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

Спасибо, значит я — в начале пути.
И, похоже без бутстрапов мне, как фуллстеку, интерфейсную ветку не прокачать.
P.S. до написания миксинов к компонентам мне еще далеко, SCSS вида
@for $i from 0 to length($selectors) {
    #{nth($selectors, $i + 1)} {
      position: absolute;
      height: $height;
      margin-top: $i * $height;
    }
  }
это совершенно особенная жесть свой мир

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


А те миксины, про которые я говорил — простейшие наборы статичных параметров типа .inline-block() { vertical-align: top; display: inline-block; }, такие вот небольшие кирпичики. Динамические параметры в стили сейчас передаются с помощью Custom CSS Variables, то есть в стилях пишешь .myClass { color: var(--main-color) } и затем при изменении этого свойства у родительского элемента этот чайлд перекрасится. Монструозные либы с кучей логики как-то ушли в прошлое и только на простых сайтах используются, ввиду сложностей кастомизации.

Спасибо, сто делает код мне было известно, но только потому что это пример из документации по SASS. Пугает конструкция #{выражение}. Но раз не нужно, то все не так страшно ;)

Все думал у кого спросить — как с SVG макетами работать? (Или какие там сейчас макеты?)

Сейчас макеты выгружают в Figma / Zeplin, они там в векторном формате. При клике на элемент эти инструменты сами генерируют css стили — размеры, цвета, шрифты, остается просто скопировать к себе и настроить раскладку блоков и адаптивность. Иконки или растровая графика парой кликов выгружаются в svg или jpg, в общем, верстать стало намного проще.


Раньше да, приходилось из Photoshop / Illustrator / Corel Draw самостоятельно вычислять размеры, черри-пикать цвета, сложнее определять отступы от элементов и сложнее экспортить иконки / растровые изображения.


Конструкции #{выражение} действительно страшновато выглядят, но в реальных приложениях годы назад только такое видел, а сам писал последний раз в 2014 типа таких систем раскладок (LESS)


.row(@columns:@columns) {
  width: @total-width*((@gutter-width + @gridsystem-width)/@gridsystem-width);
  margin: 0 @total-width*(((@gutter-width*.5)/@gridsystem-width)*-1);
  .clearfix;
}
.grid(@n, @i: 1) when (@i =< @n)  {
  .grid(@n, (@i + 1));
}

Но это контрпродуктивно и подходит только для унифицированных раскладок интерфейса

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

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


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

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

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

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

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

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

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

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

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


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

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

Рассматривать отдельные подсистемы как фреймворки — перебор, как минимум для данной статьи, что может смутить начинающих разработчиков. В остальном конечно react можно считать чем-то большим, чем библиотеку, для кого-то это действительно фреймворк, если помимо отображения использовать Context API для управления данными
Ну хорошо, положим что Реакт не дотягивает до SPA фреймворка. Что насчет vue? Разве там можно из коробки управлять глобальным стейтом и писать роутинг? Насколько я знаю для этого есть соответствующие либы vuex и vue-router которые идут отдельно? Почему же Vue называют фреймворком?
А что у svelte? У него есть в комплекте роутинг и работа со сторами уровня Redux/vuex или опять пишите депенденсы?
Получается что либо у нас единственный фреймворк angular(JS), либо просто учитываем то что написал автор на офф странице.
Тут есть несколько поинтов.
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, где можно собрать по описаному гайду приложение и оправить его в условный продакшен.

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


В вебе существует большая проблема — статичность интерфейсного слоя и сложность взаимодействия с ним, 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% юниты для утилит и функций преобразования данных, тестирование отдельных компонентов на моковых данных дает слишком мало гарантий. Так что соглашусь отчасти — реактовые компоненты изолированно тестировать сложно, но это и не нужно.

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

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

В кучу можно при любом подходе смешать, я говорил про синтаксис. Реактовый {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, но большой проблемы в этом не вижу.

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

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

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


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


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


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


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

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


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

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


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

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


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

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

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

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

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

Опять же, реакт вообще не про это и не для этого. Тут на помощь идеально приходит MobX.
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.

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

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

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

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

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

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

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


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


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

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

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

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

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

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

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

Считаю, очень заслуживает внимания!
Спасибо за информацию по инструменту!
В данный обзор данный квазар уже точно не попадет, но попробую сделать тест-драйв и в дальнейшем упомянуть в смежных статьях, если такие будут
Sign up to leave a comment.