Інтерв'ю c Max Stoiber і Сергієм Лапіним: Вибираємо state management рішення для React.js



Напередодні конференції HolyJS ми поговорили з Максом Штойбером (одним з організаторів React.js Vienna Meetup, творцем react-boilerplate, брали участь і в створенні Carte Blanche) і Сергієм Лапіним (членом програмного комітету HolyJS) і обговорили, як вибрати state management рішення.

Redux, MobX, Relay або інша реалізація Flux? Практичні рекомендації та найкращі практики.

Макс Штойбер
Макс, привіт! Для початку коротко відрекомендуйся і розкажи про себе.

– Привіт! Мене звуть Макс Штойбер, я Open Source розробник, працюю в компанії Thinkmill. Ми робимо всякі прикольні штуки на зразок KeystoneJS, розробляємо веб — і мобільних додатків, вносимо свій внесок у поліпшення User Experience.

– Звучить круто! Розкажи, як давно ти всім цим займаєшся, коли відкрив для себе React, і в яких проектах брав участь?

– Хмм, здається, я з React'му вже приблизно 2,5 року. Коли я починав, Flux вважалася найбільш «гарячою» темою в світі! Мабуть, найбільш відомі проекти, в яких я брав участь, це KeystoneJS, react-boilerplate і sharingbuttons.io.

Від Flux до Redux
– Думаю, що тепер у читачів склалося враження про те, хто перед ними. Як ти знаєш, наша основна тема сьогодні — це «React Redux на довгих дистанціях: чи потрібен він у великих проектах?». Давай почнемо з того, що ти думаєш про концепції Flux і які реалізації встиг спробувати на сьогоднішній день.

– Я дуже люблю Flux! Думаю, це чудова ідея — зробити потік даних однонаправленим.



Це настільки спрощує роботу зі станом додатки і полегшує життя, що складно повірити, що колись було інакше. Flux чудово масштабується для додатків будь-яких розмірів, дозволяє інтуїтивно розбивати роботу зі статком у відповідності з бізнес-логікою різних частин програми. Складно переоцінити цю концепцію, коли необхідно «дробити» частини проекту і розподіляти їх між членами команди. Спочатку я використовував оригінальний Flux, але переключився на redux майже відразу ж після його релізу.

– Що ти думаєш про redux в цілому? Як ставишся до необхідності писати купу boilerplate коду?

– Я використовую redux скрізь і обожнюю його. Я зовсім не проти писати boilerplate код, більше того, мені дуже подобається, що вся описана логіка явно і не відбувається ніякої «магії». Redux змінив мій підхід до розробки React-додатків. Зараз я групую файли за принципом того, які фічі вони реалізують. Коли мені потрібно змінити або доповнити якусь фічу, я просто шукаю відповідну папку і бачу всю картину відразу без необхідності проводити пошук по всьому проектом і згадувати, де у мене.

Про роботу зі State і про майбутнє
– Як ти працюєш з стейтом? Наприклад, нормализуешь ти дані, які до тебе приходять від back-end'ів, розгортаєш Array у Map'и, використовуєш Immutable?

– Оу, здається, у вашого сайту дуже технічна аудиторія. Так, ти все правильно сказав: це кращі практики на поточний момент. Можу додати лише селектори. Я використовую reselect, щоб мої компоненти могли абстрагуватися від структури стейта і отримували дані в зручному для них вигляді.

OK, з Redux все більш або менш ясно. Давай обговоримо дві інші реалізації Flux: MobX і Relay. А також, що ти думаєш про майбутнє state management рішень?

– У мене немає досвіду застосування MobX у великих проектах, але він виглядає досить багатообіцяюче, і я не раз всерйоз розглядав його в якості альтернативи redux-у. Якщо ж говорити про Relay, то це прекрасне рішення, але з одним великим недоліком: твій back-end повинен бути у форматі GraphQL. Чесно кажучи, недавнє опитування лише підтвердив моє відчуття, що ринок рішень по роботі з стейтом вже склався, і ситуація навряд чи сильно зміниться в найближчому майбутньому.



Якщо не любиш «магію», то redux — твій вибір
– Якщо б я прийшов до тебе з питанням: «Привіт, Макс! Я збираюся зробити новий великий проект і не знаю, яку state management бібліотеку вибрати», що б ти порадив?

– Хороше питання. Якщо твій back-end вміє GraphQL, то можна брати Relay (або Apollo Client), не замислюючись. З MobX і redux вибір дещо складніше. Якщо ти любиш експериментувати і готовий витратити трохи часу, щоб вся твоя команда вивчила нове рішення, то вибір MobX здається виправданим, принаймні, я чув багато хорошого про нього останнім часом. Ну, а якщо ти не любиш «магію», тебе підтискають терміни або ти хочеш скоріше запустити свій проект в продакшн, то redux — твій вибір.

– Що ж, дякую за твою пораду! Я знаю, що ти скоро приїдеш до Москви на конференцію HolyJS. Про що ти плануєш розповісти?

– Я буду розповідати про offline. За допомогою цієї технології веб-додатки зможуть наблизитися до нативним додатками. Якщо коротко, то ServiceWorkers дозволяють розробнику визначати, що має робити його застосування або поганому інтернеті або його відсутності. Це зовсім молода технологія, тому усталених рішень ще немає, але sw-precache, sw-toolbox і webpack offline-plugin виглядають багатообіцяюче.

Макс, дякую за твій час! До зустрічі на конференції!

– Дякую за цікаві запитання, до зустрічі в Москві.

Інтерв'ю брав @YuryDymov

Сергій Лапін

— Привіт, Сергій. Будеш, будь ласка, і розкажи читачам про те, чим ти займаєшся?

— Привіт! Мене звуть Сергій Лапін. Я фрілансер, роблю проекти виключно на React JS і в основному використовую Redux. Зараз вже третій проект роблю на ньому. За сумісництвом один з організаторів HolyJS і SPB Frontend.

Чому Flux-Redux?
— Розкажи, чому саме Flux і Redux? Чому ти вибрав саме цей підхід для створення клієнтських додатків?

— Основне, чим гарний цей підхід — односпрямований потік даних. Будь-який стан системи при такому підході визначається послідовністю цих action (дій). Теоретично це означає, що якщо ми дамо Flux цю послідовність, то на виході ми отримаємо шукане стан системи. Але найважливіше, що просто вивівши ці екшени в консоль, легко зрозуміти, що взагалі відбувається. Це має величезний ефект для дебага.

Ми не можемо отримати цей лог подій в традиційних MVC/MVVP та інших системах, тому що ми неявно змінюємо модель, смикаючи ті чи інші методи. Також моделі можуть впливати на інші моделі, це все викликає каскад змін UI, і зрозуміти, що від чого залежить, і підтримувати це все стає дуже важко. Тому, якщо хочеться змінити стан, ми б'ємо себе по руках. Тепер, будь ласкавий, створи екшн і передай його через Dispatcher, який в системі єдиний.

Redux також пропонує думати про додатку, як про початковому стані модифікованому послідовністю дій.

Redux краще?
— Добре. Але чим тоді Redux краще інших Flux'ів і State контейнерів?

— Важливо розуміти, що Redux — це не зовсім Flux. Його основна відмінність в тому, що в Redux немає в явному вигляді Dispatcher і Store'ів. Сховища злилися в одне велике сховище. Також Redux вміє диспатчить дій (створювати події). Стало менше самостійних сутностей. Але найголовніше, що односпрямований потік даних залишився.

Одна з ключових ідей Redux — редюсеры (The Reducers). Ніщо не взаємодіє зі станом безпосередньо. Замість цього кожен шматочок копіюється, а потім всі шматочки об'єднуються в новий об'єкт стану. Редюсеры передають свої копії назад кореневого редюсеру, що «склеює» копії разом для формування оновленого об'єкта стану. Потім головний редюсер передає отриманий таким чином об'єкт стану назад у сховище, а сховище робить його новим «офіційним» станом.

Якщо у вас невеликий додаток, можна використовувати тільки один редюсер, який робить копію об'єкта стану і його зміни. Якщо ж додаток велика, то може знадобитися ціле дерево редюсеров. Це ще одна відмінність між Flux і Redux. У Flux сховища не обов'язково пов'язані один з одним і вони мають плоску структуру. У Redux редюсеры знаходяться в ієрархії і вона може мати стільки рівнів, скільки буде потрібно.

Це не єдина відмінність Redux від Flux. Творець Redux Данило Абрамов хотів поліпшити Flux, але в теж час зберегти передбачуваність, яку дає ця архітектура. У нього вийшло.

— Чому ти віддаєш перевагу Redux, а не іншим реалізацій Flux, MobX або Relay?

Зараз Redux вже дуже популярний, можна сказати – мейнстрім: у нього чудова документація, величезна екосистема. Це в якомусь сенсі конструктор ЛЕГО. У Redux є безліч точок для розширення: Middlewares, Enhancers, HighOrderReducers і т. д.

Наприклад, Middlewares. Якщо взяти звичайний Redux з npm, то там немає жодного рішення для асинхронної роботи з даними. Даєш йому action, отримуєш новий стейт і UI, за один «тік» все синхронно. Але ж у реальному світі не буває, нам треба сходити в мережу, забрати щось з бази даних, і це може викликати ще яку-небудь асинхронщину. Бізнес-логіка в основному і складається з такої ось асинхронщины. Тут магію робить Мiddleware, вони працюють в принципі один в один як в Koa.

Для роботи з асинхронностью є багато ком'юніті-рішень:

Хочемо диспатчить промисы — Мiddleware. Хочемо показати прогрес бар скрізь у додатку, коли щось довго завантажується — Мiddleware. Хочемо при exception посилати помилки користувачів з логом екшенів — ну ви зрозуміли.

Схожа історія з Enhancers і HighOrderReducers — центральне сховище дає багато можливостей для контролю.

Досвід роботи з Redux
— У тебе вже великий досвід роботи з Redux. Які у нього є проблеми і обмеження? З якими труднощами зіткнувся ти в процесі розробки проектів?

— Наприклад, у мене був проект — платформа для навчальних курсів. Це додаток на React, в якому багато віджетів для роботи з зображеннями, графіками, графами і т. д. По суті, це відкотити, кожне з яких має свою логіку, свій цикл релізу, і найголовніше — свій стейт, який всім іншим не особливо цікавий.

Зазвичай з Redux і React не виникає проблем з продуктивністю, але якщо вкладеність компонентів велика, то, прокидывая всі зміни через центральне сховище, починаєш відчувати затримку. В результаті довелося синхронізувати ці стейты з Redux'ом досить хитрим чином. Був кумедний експеримент з Redux'ом всередині Redux'а.

Є така концепція — контейнери та презентаційні компоненти. Досить довго я вважав, що проміжний стейт це зло. Компоненти варто робити максимально чистими і все зберігати в Redux. Тепер я так не вважаю.

Наприклад, навіщо будь-зміни у формі диспатчить нагору? Тільки атмосферу так гріти… Потрібен проміжний стейт. Я не великий фанат класів, тому з допомогою recompose оборачиваю stateless в statefull component'и. Це дозволяє не переписувати існуючий код в класи.

— Які помилки часто роблять у Redux початківці розробники?

– Люди забувають, що reducer'и повинні завжди створювати новий об'єкт. Поширена помилка забувати, що spread не робить глибокого мерджа:

const newNested = {...oldState.nested, ...newState.nested };
const finalState = { ...oldState, nested: newNested };

Також часто зашивають дуже багато логіки в контейнери. Її краще виносити в Action Creator'и: там їх простіше компонувати і можна дістати поточний стейт у Redux.
А ще краще нормалізувалася стейт.

— чи Є в тебе якісь поради з розряду «Best Practices» для розробки в Redux?

– Насамперед, не варто сліпо копіювати чужі проекти. Можна взяти якийсь boilerplate і на швидку руку вирішити завдання, але потім потрібно розібратися, що ви власне взяли. Викинути те, що не потрібно, і зрозуміти, як працює те, що ви залишили.

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

З плином часу ви можете переростати ті чи інші підходи, викидати одні Мiddleware, використовувати інші. Через рік можна не впізнати проект, хоча це буде той же Redux. Це, як мені здається, і є саме круте в ньому — здатність пристосовуватися до вимог проекту.

HolyJS
— Та розкажи наостанок про конференції HolyJS. Чим ти там займаєшся?
– Я в програмному комітеті, ми відбираємо і прослуховуємо доповіді для конференції, сам виступати не буду.

– Спасибі за відповіді!

Розмовляв levashove



Також в рамках конференції HolyJS реєстрація) можна буде послухати наступні доповіді:

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.