Створення налаштовуваного компонента вибору для React Native Paper
Покрокове керівництво з проектування та оприлюднення коду react-native-paper-select у відкритому доступі, яке охоплює функції пошуку, багатократний вибір елементів, розділені списки та компроміси щодо продуктивності.
Створення справжнього спадного меню в React Native майже ніколи не є настільки простим, як здається
Якщо ви витратили час на спробу реалізувати належне спадне меню в React Native, ви вже знаєте, що «просто спадне меню» швидко перетворюється на набагато складніше завдання.
Вам доводиться керувати станом вибору, підключати функції пошуку, підтримувати багатократний вибір, працювати з довгими списками, формувати інтерфейс у спосіб, який здається природним для мобільних пристроїв, додавати перевірки та стежити за тим, щоб все це візуально гармоніювало з рештою вашого додатку.
Якщо ваш проєкт вже побудований на основі React Native Paper, використання окремої бібліотеки інтерфейсу лише для створення функціонального поля вибору здається зайвим.
Саме ця невідповідність є проблемою, яку було створено для вирішення цей компонент.
Метою був повторно використовуваний компонент вибору, який би гармонійно вписувався у React Native Paper, підтримував як одиночний, так і багатократний вибір, та дозволяв уникнути необхідності постійного повторного створення однакових шаблонів взаємодії у кожному проекті.
Тож його було створено з нуля.
Те, що спочатку було досить вузькоспрямованим компонентом інтерфейсу, з часом перетворилося на react-native-paper-select — багатофункціональний пакет для React Native з відкритим кодом, який тепер включає функції пошуку, багатократного вибору, відображення даних у форматі чіпів, розділених списків, вибору за допомогою кнопок-радіо, нижніх панелей, меню та ефективного відображення списків.
У цій статті розглядаються причини його створення, як компонент змінювався з часом, інженерні рішення, які вплинули на його розвиток, та уроки, отримані під час перетворення інструменту, спочатку створеного для одного додатку, на універсальну бібліотеку з відкритим кодом.
Проблема
На перший погляд, списки випадання здаються простими.
Однак як тільки ви починаєте їх реалізовувати, з’являється довгий список дизайнерських питань:
- Як відображати поточне обране значення?
- Чи потрібно, щоб поле підтримувало один вибір чи кілька?
- Який правильний формат для списку варіантів?
- Як має працювати пошук у цьому списку?
- Чи має поведінка відрізнятися між Android та iOS?
- Як відображати дуже довгі списки, не погіршуючи продуктивність?
- Як зробити API для розробників простим?
- Як дозволити налаштування, не перетворюючи компонент на щось складне у використанні?
Розв’язувати ці питання з нуля в кожному окремому додатку не мало сенсу.
Замість створення ще одного унікального компонента, призначеного конкретно для додатку, було доцільніше з самого початку розробити щось, що можна буде використовувати знову.
Основна ідея була простою:
Створити компонент для вибору на основі власних UI-елементів React Native Paper та зробити його настільки зручним, щоб інші розробники React Native справді захотіли ним скористатися.
Представляємо react-native-paper-select
react-native-paper-select — це налаштовуваний компонент для React Native, який підтримує як ситуації однократного, так і багатократного вибору.
У першій версії використовувалися вже наявні у React Native Paper елементи, зокрема:
TextInputCheckboxDialog
Метою було надати розробникам можливість вибору, яка б візуально та функціонально відповідала додаткам, вже створеним за допомогою системи дизайну React Native Paper.
У міру розвитку пакету він вийшов за межі початкової реалізації, щоб підтримувати додаткові стилі візуалізації та більш розширену логіку вибору.
Встановлення пакета
Щоб почати працювати, потрібно лише кілька кроків.
npm install react-native-paper-select
Або, якщо ви віддаєте перевагу Yarn:
yarn add react-native-paper-select
Після встановлення імпортуйте компонент ось так:
import { PaperSelect } from 'react-native-paper-select';
Базовий Select
Щоб створити мінімальне поле вибору, вам потрібен лише список опцій та функція для обробки вибору.
Ось приклад:
const [selected, setSelected] = useState({
value: '',
label: '',
});
const options = [
{
_id: '1',
value: 'React Native',
},
{
_id: '2',
value: 'Flutter',
},
{
_id: '3',
value: 'Native Android',
},
];
А потім відобразіть компонент:
<PaperSelect
label="Framework"
value={selected.label}
onSelection={(value) => setSelected(value)}
arrayList={options}
selectedArrayList={selected}
/>
Тут важливо не те, наскільки мало коду потрібно.
Важливо те, що приховує цей код.
З точки зору додатку насправді існує лише два запитання, які потрібно відповісти:
Які опції доступні?
та
Що обрав користувач?
Усе, що стосується візуалізації та взаємодії, обробляється безпосередньо самим компонентом.
Вибір одного елемента проти вибору кількох
Підтримка як вибору одного елемента, так і вибору кількох з самого початку була однією з ключових вимог до цього компонента.
Механізм вибору одного елемента досить простий у розумінні:
Select Framework
----------------
○ React Native
○ Flutter
○ Native Android
Однак механізм вибору кількох елементів потребує додаткового керування станом:
Select Technologies
-------------------
☑ React Native
☑ TypeScript
☐ Flutter
☑ Node.js
Це означає, що компонент мусить піклуватися про:
- Відстеження стану вибору
- Обробку скасування вибору
- Відображення кількох обраних значень одночасно
- Повернення оновленого набору обраних елементів
Метою було утримати всю цю складність всередині самого компонента, а не перекладати її на кожного розробника, який використовує пакет.
Чому React Native Paper?
Оскільки основне додатку вже базувалося на React Native Paper, створення компонента select на основі цієї ж системи дизайну було логічним вибором.
Замість того, щоб заново створювати кожен візуальний елемент, компонент міг повторно використовувати елементи інтерфейсу, які вже надавав Paper.
На високому рівні внутрішня структура виглядала приблизно так:
PaperSelect
│
┌──────────┴──────────┐
│ │
TextInput Selection UI
│
┌───────────┼───────────┐
│ │ │
Checkbox Radio List
Цей вибір дизайну приносить реальну користь.
Будь-який додаток, який вже використовує React Native Paper, може додати цей компонент select без впровадження візуального стилю, який би конфліктував з рештою інтерфейсу.
Найраніша версія цього компонента пропонувала лише діалогове вікно для вибору.
Інтеракція працювала так:
TextInput
↓
User taps field
↓
Dialog opens
↓
User selects an item
↓
Selected value appears in TextInput
Однак у міру розвитку компонента стало очевидно, що діалогове вікно не завжди є найкращим рішенням для кожного мобільного екрана.
Вимоги до користувацького інтерфейсу сильно відрізняються в різних додатках.
Щоб врахувати це, компонент було розширено для підтримки кількох способів відображення:
- Діалогове вікно
- Нижній листок
- Меню
Завдяки цій зміні один і той самий компонент вибору можна використовувати у дуже різних контекстах інтеракції, і розробникам не доводиться переписувати свою інтеграцію для перемикання між ними.
Наприклад:
<PaperSelect
presentationStyle="bottomSheet"
...
/>
Ця гнучкість стала значним кроком уперед для бібліотеки.
Логіка вибору залишається ідентичною незалежно від обраного стилю — змінюється лише спосіб її відображення користувачеві.
Робота з великими списками
Не такою очевидною проблемою у компонентах у форматі спадного списку є як ефективно працює список у міру його збільшення.
10 items
Це дуже просто для відображення.
Тепер уявіть собі компонент з:
1,000 items
або навіть:
10,000 items
Відображення стількох елементів списку одночасно може почати погіршувати швидкість реакції мобільного додатку.
Щоб уникнути цього, пакет використовує FlashList для відображення своїх списків опцій.
Концепція є простою:
Large dataset
↓
Virtualized list
↓
Render what is needed
↓
Better scrolling performance
Продуктивність — це проблема, яку не можна відкладати до моменту створення чогось масштабного.
Будь-який компонент, призначений для повторного використання, має бути створений з урахуванням масштабу вже з самого початку, адже рідко можна заздалегідь знати, наскільки великими будуть надані йому набори даних.
Пошук
Чим більше варіантів для вибору, тим важливішим стає пошук.
Замість того, щоб змушувати користувачів безкінечно прокручувати довгий список, компонент пропонує можливість пошуку для скорочення вибору.
Потік дій виглядає так:
Search
↓
Filter options
↓
Select result
↓
Update selection
З точки зору користувача це може здатися незначним доповненням, але воно суттєво впливає на зручність використання, коли обсяг даних перевищує кілька елементів.
Багатовибірковий режим з іконками
Відображення кількох обраних значень одночасно швидко призводить до зайвої заплутаності.
Наприклад, значення на кшталт:
React Native, TypeScript, Node.js, MongoDB
важко розпізнати, якщо його помістити у стандартне поле введення тексту.
Іконки вирішують цю проблему.
Вибрані значення можна також відображати як окремі, чітко визначені блоки:
[ React Native ] [ TypeScript ]
[ Node.js ] [ MongoDB ]
Цей компонент підтримує такий дисплей на основі чипів у сценаріях багатовибору, що дає користувачам набагато чіткіше уявлення про те, що вони обрали.
Це також робить видалення окремих виборів набагато інтуїтивнішим.
Роздільні списки
Ще однією вимогою була можливість групувати пов’язані опції разом.
Замість одного довгого, рівного списку на кшталт:
React
Angular
Vue
Node.js
Java
Python
MongoDB
PostgreSQL
опції можна організувати під заголовками:
Frontend
☐ React
☐ Angular
☐ Vue
Backend☐ Node.js
☐ Java
☐ Python
Database☐ MongoDB
☐ PostgreSQL
Таке групування значно полегшує огляд та розуміння великих наборів опцій.
У режимі багатовибору можливість обирати цілу секцію одночасно значно прискорює процес.
Наприклад:
☑ Frontend
☑ React
☑ Angular
☑ Vue
Це краще, ніж змушувати користувача торкатися кожного елемента по черзі.
Полічки для одиночного вибору
Полізначки є доцільними, коли можна вибрати більше одного варіанта.
Але у сценаріях одиночного вибору полічки чіткіше доносять намір до користувача.
Саме тому пакет також пропонує варіант інтерфейсу вибору у вигляді полічок.
Основна ідея залишається незмінною:
Options
↓
User chooses one
↓
Selection state updated
Змінюється лише візуальне представлення.
Це підкреслює важливий принцип створення повторно використовуваних компонентів:
Тримайте логіку вибору окремо від способу її візуального відображення.
TypeScript та проектування API
Оскільки цей інструмент призначений для використання іншими розробниками, форма API має таке ж значення, як і вигляд інтерфейсу.
Той, хто використовує пакет, не повинен знати нічого про його внутрішню роботу.
Ідеально, якщо вони можуть міркувати щодо цього виключно з точки зору:
Input
↓
Options
↓
User interaction
↓
Selection
↓
Callback
замість:
Dialog state
Modal state
List state
Search state
Checkbox state
Rendering state
...
Добре спроєктований API компонента приховує цю внутрішню складність від користувача.
Це один із найясніших уроків, отриманих під час створення та вдосконалення цього пакету.
Опен-сорс змінює спосіб розробки
Написання компонента для власного додатку — це інше завдання, ніж написання його для ширшої аудиторії розробників.
У межах одного додатку вимоги можуть бути такими:
"Це вирішує мою конкретну проблему."
Коли продукт стає опен-сорсом, питання змінюється на:
"Чи буде цей API зрозумілим розробнику, який ніколи не бачив вихідного коду?"
Ця зміна впливає на ваші пріоритети під час розробки.
Раптово ви починаєте приділяти набагато більше уваги таким речам:
- Цілісність API
- Документація
- Зворотна сумісність
- Крайні випадки
- Розумні значення за замовчуванням
- Визначення типів
- Опції налаштування
- Продуктивність
- Версіонування
Те, що спочатку було невеликим, простим компонентом, може перетворитися на щось дивовижно складне, коли інші розробники починають покладатися на нього у продакшені.
Як проект розвивався з часом
Те, що починалося як простий компонент вибору, поступово перетворилося на більш повний набір інструментів для вибору.
Його розвиток можна приблизно описати так:
Simple Select
↓
Single Selection
↓
Multi Selection
↓
Search
↓
Large List Handling
↓
Chips
↓
Sections
↓
Radio Selection
↓
Bottom Sheet
↓
Menu Presentation
Кожна нова функція вирішувала реальну проблему, пов’язану з користувацькістю чи досвідом розробника.
Це один із аспектів розробки відкритих продуктів, який виділяється.
Коли ви розсилаєте версію 1, у вас рідко є чітке уявлення про те, як буде виглядати готова бібліотека у кінцевому підсумку.
Натомість структура пакету постійно змінюється у міру виникнення реальних вимог, відгуків користувачів та нових сценаріїв використання.
Уроки з цього процесу
1. Незначні проблеми можуть перетворитися на корисні проекти з відкритим кодом
Початкова проблема жодним чином не була революційною.
Просто бракувало компонента select, який можна було б використовувати знову.
Але існує справжня різниця між тим, щоб виправити щось для власних потреб, та тим, щоб довести його до рівня, коли інші люди також зможуть його взяти та використовувати.
Іноді ця різниця є достатньо великою, щоб обґрунтувати створення проекту з відкритим кодом.
2. Щоб щось стало відновлюваним, потрібно належним чином абстрагувати його
Добре спроєктований компонент не повинен бути прив’язаним до конкретного додатку, який його створив.
Натомість він має мати чистий, простий інтерфейс ззовні, приховуючи свою внутрішню складність.
Цей принцип застосовується не лише у світі React Native.
3. Дизайн компонентів також стосується користувацького досвіду
Робити компонент пере використовуваним на рівні коду — це не все.
Не менш важливим є те, які враження справляє взаємодія з ним.
Діалогові вікна, нижні панелі, меню, іконки, поля пошуку, кнопки вибору та розділені списки — це просто різні варіанти відповіді на одне основне питання:
Який найкращий спосіб дозволити користувачеві зробити вибір?
4. Пере використовувані компоненти мають будуватися з урахуванням продуктивності
Компонент, який добре працює з десятьма елементами, може згодом використовуватися там, де їх десять тисяч.
Саме тому рішення щодо відображення списків та віртуалізації мають прийматися на етапі проектування, а не як пізніше доповнення, коли у продакшені починають з’являтися проблеми з продуктивністю.
5. Документація є основною частиною пакету, а не додатком
Одного лише працездатного коду недостатньо, щоб вважати пакет готовим.
Розробникам все ще потрібні чіткі відповіді на такі питання:
- Як його встановити
- Як ним користуватися
- Які параметри є доступними
- У якій формі мають бути дані
- Як налаштувати його функціонування та вигляд
- Які функції насправді підтримуються
Якісна документація — це те, що подолує розрив між ситуацією, коли хтось думає:
"I found this package."
і моментом, коли він може з упевненістю сказати:
"I can use this package."
Яким буде подальший розвиток проекту
Спочатку мета проекту react-native-paper-select була скромною: створити компонент вибору, який би природно інтегрувався у додатки, що вже використовують React Native Paper.
З того часу він перетворився на набагато потужніший інструмент, який тепер підтримує кілька режимів вибору, різні стилі відображення, пошук, вибір за допомогою чіпів, розділені дані та ефективне відображення списків.
Ще є багато можливостей для його подальшого вдосконалення.
Жоден проект з відкритим кодом ніколи не стає повністю завершеним.
Постійно з’являються нові пристрої, React Native сам продовжує випускати оновлення, змінюються очікування щодо дизайну, розвиваються вимоги до доступності, знову постають питання продуктивності, а розробники постійно надсилають корисні відгуки.
Саме ця постійна еволюція робить підтримку такої бібліотеки справді цікавою.
Заключні думки
Робота над react-native-paper-select показала, що проект з відкритим кодом не обов’язково має починатися з великої ідеї.
Часто все починається з невеликої, конкретної проблеми, з якою стикаєшся під час розробки чогось іншого.
Ти сам її вирішуєш.
Потім стає зрозуміло, що це рішення може допомогти іншим, хто стикається з тією самою проблемою.
Тож ти його удосконалюєш.
Ти належним чином його описуєш.
Ти оприлюднюєш його.
З часом невеликий внутрішній компонент може перетворитися на пакет, від якого залежать інші розробники у своїх проектах.
Ось історія створення react-native-paper-select.
Якщо ваш проєкт використовує React Native Paper та вам потрібен гнучкий компонент для вибору або багатократного вибору, репозиторій знаходиться на GitHub, а сам пакет опублікований на npm.
Будь-які відгуки, звіти про помилки та ваші внески завжди будуть корисними, якщо ви будете використовувати цей пакет.