• Главная
  • Карта сайта
Не найдено

SavePearlHarbor

  1. Управління станом додатки, інтеграція з Redux, організація маршрутизації
  2. ▍Решеніе завдань, які не можна вирішити за допомогою чистих функцій
  3. ▍Внедреніе редьюсеров
  4. ▍Маршрутізація і Redux
  5. Динамічний призначений для користувача інтерфейс і потреби зростаючого додатки
  6. ▍Ленівая завантаження і React.Suspense
  7. ▍Адаптівние компоненти
  8. Підсумки

Сьогодні ми публікуємо другу частину перекладу матеріалу, який присвячений розробці великомасштабних React-додатків. Тут мова піде про управління станом додатків, про маршрутизації і про розробку інтерфейсів.

Тут мова піде про управління станом додатків, про маршрутизації і про розробку інтерфейсів

Управління станом додатки, інтеграція з Redux, організація маршрутизації

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

Функції-генератори в JavaScript можуть вирішити безліч проблем, супутніх асинхронного програмування. Справа в тому, що ці функції можна запускати і зупиняти за бажанням програміста. ПО проміжного рівня redux-saga використовує цю концепцію для управління проблемними аспектами програми. Зокрема, мова йде про рішення таких задач, вирішити які не виходить за допомогою редьюсеров, представлених у вигляді чистих функцій.

▍Решеніе завдань, які не можна вирішити за допомогою чистих функцій

Розглянемо наступний сценарій. Вам запропонували попрацювати над додатком, призначеним для компанії, яка працює на ринку нерухомості. Клієнт хоче обзавестися новим, більш якісним веб-сайтом. У вашому розпорядженні є REST API, у вас є макети всіх сторінок, підготовлені за допомогою Zapier, ви накидали план додатки. Але тут підкралася здоровенна проблема.

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

Добре те, що CMS, яка використовується клієнтом, має зручний API, через який можна отримати доступ до публікацій з блогу. Але, якщо ви створили агент для роботи з цим API, ситуацію ускладнює те, що воно знаходиться на якомусь сервері, на якому дані представлені зовсім не так, як вам потрібно.

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

Схема додатки, в якому використовується сховище Redux і redux-saga

Тут компонент виконує відправку дії GET.BLOGS. У додатку використовується redux-saga, тому цей запит буде перехоплений. Після цього функція-генератор в фоновому режимі завантажить дані зі сховища даних і оновить стан додатки, підтримуване засобами Redux.

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

... function * fetchPosts (action) {if (action.type === WP_POSTS.LIST.REQUESTED) {try {const response = yield call (wpGet, {model: WP_POSTS.MODEL, contentType: APPLICATION_JSON, query: action. payload.query,}); if (response.error) {yield put ({type: WP_POSTS.LIST.FAILED, payload: response.error.response.data.msg,}); return; yield put ({type: WP_POSTS.LIST.SUCCESS, payload: {posts: response.data, total: response.headers [ 'x-wp-total'], query: action.payload.query,}, view: action. view,}); } Catch (e) {yield put ({type: WP_POSTS.LIST.FAILED, payload: e.message}); ...

Представлена ​​тут сага чекає появи дій типу WP_POSTS.LIST.REQUESTED. Отримуючи таку дію, вона завантажує дані з API. Вона ж, після отримання даних, відправляє іншу дію - WP_POSTS.LIST.SUCCESS. Його обробка призводить до оновлення сховища з використанням відповідного редьюсера.

▍Внедреніе редьюсеров

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

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

Впровадження редьюсеров - це форма поділу коду. Спільнота React-розробників з ентузіазмом освоює цю технологію. Я буду користуватися цим фрагментом коду для того щоб продемонструвати зовнішній вигляд і особливості роботи механізму впровадження редьюсеров.

Для початку подивимося на його інтеграцію з Redux:

... const withConnect = connect (mapStateToProps, mapDispatchToProps,); const withReducer = injectReducer ({key: BLOG_VIEW, reducer: blogReducer,}); class BlogPage extends React.Component {...} export default compose (withReducer, withConnect,) (BlogPage);

Цей код є частиною файлу BlogPage.js, який містить компонент програми.

Тут ми, в команді експорт, застосовується НЕ функцію connect, а функцію compose. Це - одна з функцій бібліотеки Redux, яка дозволяє виконувати композицію декількох функцій. Список функцій, переданих compose, треба читати справа наліво або від низу до верху.

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

Сама права функція в композиції може приймати безліч аргументів, але функцій, наступним за нею, може передаватися лише один аргумент. У підсумку, викликаючи ту функцію, яка вийшла в результаті використання compose, ми передаємо їй то, що приймає та з вихідних функцій, яка знаходиться правіше всіх інших. Саме тому ми передали функції compose функцію withConnect в якості останнього параметра. В результаті функція compose може бути використана точно так само як функція connect.

▍Маршрутізація і Redux

Існує цілий ряд інструментів, які використовуються для вирішення задач маршрутизації в додатках. У цьому розділі ми, однак, зупинимося на бібліотеці react-router-dom . Ми розширимо її можливості таким чином, щоб вона могла б працювати з Redux.

Найчастіше маршрутизатор React використовують так: кореневої компонент укладають в тег BrowserRouter, а дочірні контейнери обертають в метод withRouter () і експортують їх ( вісь приклад).

При такому підході дочірній компонент отримує, через механізм props, об'єкт history, що містить деякі властивості, специфічні для поточної сесії користувача. В цьому об'єкті є і деякі методи, які можуть бути використані для управління навігацією.

Такий варіант маршрутизації може призводити до виникнення проблем у великих додатках. Відбувається це через те, що в них немає якогось централізованого об'єкту history. Крім того, компоненти, що не Рендер за допомогою <Route>, не можуть працювати з об'єктом history. Ось приклад використання <Route>:

<Route path = "/" exact component = {HomePage} />

Для вирішення цієї проблеми ми скористаємося бібліотекою connected-react-router , Яка дозволить налагодити маршрутизацію з використанням методу dispatch. Інтеграція в проект цієї бібліотеки потребують виконати деякі модифікації. Зокрема - потрібно буде створити новий редьюсер, призначений спеціально для маршрутів (це цілком очевидно), а так само - додати в систему деякі допоміжні механізми.

Новою системою маршрутизації, після завершення її налаштування, можна користуватися за допомогою Redux. Так, навігація в додатку може бути реалізована шляхом відправки дій.

Для того щоб скористатися можливостями бібліотеки connected-react-router в компоненті, ми просто виконуємо меппінг методу dispatch на сховище, роблячи це відповідно до потреб додатки. Ось приклад коду, який демонструє використання бібліотеки connected-react-router (для того щоб подібний код заробив, потрібно, щоб і інші частини системи були б налаштовані на використання connected-react-router).

import {push} from 'connected-react-router' ... const mapDispatchToProps = dispatch => ({goTo: payload => {dispatch (push (payload.path));}}); class DemoComponent extends React.Component {render () {return (<Child onClick = {() => {this.props.goTo ({path: `/ gallery /`}); />} ...

Тут метод goTo відправляє дію, яке поміщає необхідний URL в стек історії браузера. Раніше був виконаний меппінг методу goTo на сховище. Тому цей метод передається DemoComponent в об'єкті props.

Динамічний призначений для користувача інтерфейс і потреби зростаючого додатки

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

▍Ленівая завантаження і React.Suspense

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

Мережеві підсистеми зазвичай сприймаються як ненадійні і схильні до помилок.

Розробник, в прагненні зробити свій додаток якомога якіснішим, може піддати його безлічі перевірок і домогтися їх успішного проходження. Але все одно є деякі речі, на зразок стану мережевого підключення або часу відповіді сервера, на які розробник вплинути не може.

Але творці програмного забезпечення не прагнуть виправдовувати неякісну роботу додатків фразами на кшталт «це не моя справа». Вони знайшли цікаві способи боротьби з мережевими проблемами.

У деяких частинах фронтенд-додатки може знадобитися показати якісь резервні матеріали (такі, які завантажуються набагато швидше, ніж реальні матеріали). Це дасть можливість позбавити користувача від споглядання «смикання» завантажуються сторінок або, що ще гірше, приблизно таких значків.

Користувачам краще нічого подібного не бачити

Технологія React Suspense дозволяє справлятися саме з такими проблемами. Наприклад, вона дозволяє вивести певний індикатор під час завантаження даних. Хоча це можна зробити і вручну, встановивши властивість isLoaded в true, використання API Suspense робить код набагато чистішим.

тут можна подивитися хороше відео про Suspense, в якому Джаред Палмер знайомить аудиторію з цією технологією і показує деякі з її можливостей на прикладі реального додатки .

Ось як робота додатка виглядає без використання Suspense.

Додаток, в якому Suspense не використовується

Оснастити компонент підтримкою Suspense набагато легше, ніж, в масштабах додатки, користуватися isLoaded. Почнемо роботу з приміщення батьківського контейнера App в React.StrictMode. Простежимо за тим, щоб серед модулів React, використовуваних в додатку, не було б тих, які вважаються застарілими.

<React.Suspense fallback = {<Spinner size = "large" />}> <ArtistDetails id = {this.props.id} /> <ArtistTopTracks /> <ArtistAlbums id = {this.props.id} /> </ React.Suspense>

Компоненти, загорнуті в теги React.Suspense, під час завантаження основного вмісту завантажують і виводять те, що вказано в властивості fallback. Потрібно прагнути до того, щоб компоненти, що використовуються у властивості fallback, мали б мінімально можливий обсяг і були б влаштовані якомога більше просто.

Додаток, в якому використовується Suspense

▍Адаптівние компоненти

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

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

У списку трас використовуються схожі елементи. Їх головна особливість полягає в тому, що на них, крім зображення і описи траси, є ще й невелике поле з вказівкою на те, чи можна глядачам гонки, що проходить на даній трасі, купити що-небудь поїсти.

Елемент для опису автомобіля і елемент для опису траси

Ці два компоненти незначно відрізняються один від одного в плані стилю (у них різний фоновий колір). Компонент, що описує трасу, містить деякі додаткові відомості про описуваному їм об'єкті реального світу, в той час як у компонента, який символізує автомобіль, таких відомостей немає. Цей приклад демонструє всього дві моделі. У великому додатку може набратися чимало подібних моделей, що розрізняються лише в дрібницях.

Створення окремих самостійних компонентів для кожної з подібних сутностей суперечить здоровому глузду.

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

Пошукова панель

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

static propTypes = {open: PropTypes.bool.isRequired, setOpen: PropTypes.func.isRequired, goTo: PropTypes.func.isRequired,};

Використовуючи цю методику можна управляти використанням HTML-класів при рендеринге подібних елементів, що дозволяє впливати на їх зовнішній вигляд.

Ще одна цікава ситуація, в якій можуть знайти застосування адаптивні компоненти - це механізм розбиття деяких матеріалів на сторінки. Навігаційна панель може бути присутнім на кожній сторінці додатка. Екземпляри цієї панелі на кожній сторінці будуть практично такими самими, як на інших сторінках.

Панель розбивки матеріалів на сторінки

Припустимо, що в якомусь додатку потрібна подібна панель. При роботі над цим додатком розробники дотримуються своєчасно сформульованих вимог. У подібній ситуації адаптивному компоненту, використовуваному для розбиття матеріалів на сторінки, потрібно передати всього пару властивостей. Це - URL і число елементів на сторінці.

Підсумки

Екосистема React в наші дні стала настільки зрілої, що навряд чи у кого-небудь виникне потреба в «винахід велосипеда» на будь-якому етапі розробки програми. Хоча це грає на руку розробникам, це призводить до того, що складно стає вибрати саме те, що добре підходить для кожного конкретного проекту.

Кожен проект унікальний в плані його масштабів і функціональності. У розробці React-додатків немає єдиного підходу або універсальних правил. Тому, перш ніж приступити до розробки, важливо її правильно спланувати.

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

І нарешті, мені хотілося б відзначити, що дані - це стрижень будь-якої програми. І React-додатки - не виняток. Із зростанням масштабів додатки ростуть і обсяги оброблюваних даних, з'являються додаткові програмні механізми для роботи з ними. Щось подібне, якщо додаток було погано спроектовано, легко може прямо-таки «розчавити» програмістів, заваливши їх складними і заплутаними завданнями. Якщо ж, в ході планування, заздалегідь були вирішені питання використання сховищ даних, якщо заздалегідь був продуманий порядок роботи дій, редьюсеров, саг, то працювати над додатком буде вже набагато легше.

Шановні читачі! Якщо вам відомі якісь бібліотеки або методології розробки, які добре показують себе при створенні великомасштабних React-додатків - просимо ними поділитися.

Якщо вам відомі якісь бібліотеки або методології розробки, які добре показують себе при створенні великомасштабних React-додатків - просимо ними поділитися

Провайдеры:
  • 08.09.2015

    Batyevka.NET предоставляет услуги доступа к сети Интернет на территории Соломенского района г. Киева.Наша миссия —... 
    Читать полностью

  • 08.09.2015
    IPNET

    Компания IPNET — это крупнейший оператор и технологический лидер на рынке телекоммуникаций Киева. Мы предоставляем... 
    Читать полностью

  • 08.09.2015
    Boryspil.Net

    Интернет-провайдер «Boryspil.net» начал свою работу в 2008 году и на данный момент является одним из крупнейших поставщиков... 
    Читать полностью

  • 08.09.2015
    4OKNET

    Наша компания работает в сфере телекоммуникационных услуг, а именно — предоставлении доступа в сеть интернет.Уже... 
    Читать полностью

  • 08.09.2015
    Телегруп

    ДП «Телегруп-Украина» – IT-компания с 15-летним опытом работы на рынке телекоммуникационных услуг, а также официальный... 
    Читать полностью

  • 08.09.2015
    Софтлинк

    Высокая скоростьМы являемся участником Украинского центра обмена трафиком (UA — IX) с включением 10 Гбит / сек... 
    Читать полностью