Нещодавно я, використовуючи React Native, займався розробкою мобільного застосунку для медитації Atomic Meditation. В ході роботи я зрозумів необхідність у вивченні та використанні TypeScript замість JavaScript у середніх та великих проєктах.
Перш ніж я почну свою розповідь, мені хотілося б відзначити, що ви зможете розібратися в цій статті, навіть якщо ніколи не користувалися React Native. Я буду все докладно пояснювати. А якщо ви робили якісь проєкти на React, то, читаючи цю статтю, можете вважати, що React і React Native - це одне і те ж. А тепер розповім про те, як звичайний JavaScript втягнув мене в неприємності.
День 1: Все йде як треба
У React Native є об'єкт AsyncStorage
, який являє собою сховище даних типу ключ/значення з асинхронним доступом до значень за ключами. Він дає розробнику дуже простий механізм для організації постійного зберігання даних на мобільному пристрої користувача.
Наприклад, скористатися ним можна так:
AsyncStorage.setItem("@key", value)
AsyncStorage
дозволяє зберігати лише строкові дані. Тому для того, щоб помістити в це сховище число - це число спочатку треба конвертувати в рядок.
Нижче показано застосування React-хука useState
для оголошення змінної sessionCount
і для установки її початкового значення в 0
. Тут же є і функція setSessionCount
, яка дозволяє змінювати стан sessionCount
:
const [sessionCount, setSessionCount] = useState(0)
Припустимо, користувач завершив сеанс медитації (я, нагадаю, займався розробкою програми для медитації). В sessionCount
зберігається загальна кількість сеансів медитації, завершених користувачем (я буду тепер називати цього користувача «Anxious Andy» - «неспокійний Енді»). Це означає, що нам треба додати 1
до значення, що зберігається в sessionCount
. Для цього викликається функція setSessionCount
, в якій і виконується додвання 1
до попереднього значення sessionCount
. А потім кількість завершених медитацій потрібно зберегти в AsyncStorage
у вигляді рядка.
Все це треба зробити в якійсь функції, яку я пропоную назвати saveData
:
// Користувач завершив сеанс медитації const saveData = () => { setSessionCount(prev => { const newSessionCount = prev + 1 AsyncStorage.setItem("@my_number", newSessionCount.toString()) return newSessionCount }) }
Все йде добре, наш Енді, тепер уже не такий неспокійний, тихо закриє додаток, відчуваючи приплив гарного самопочуття.
День 2: Затишшя перед бурею
Неспокійний Енді отримує повідомлення, яке нагадує йому про те, що через 5 хвилин починається його медитація. Але він не тільки неспокійний, але ще і нетерплячий. Тому він тут же йде до себе в кімнату, знаходить своє робоче крісло, зручно (але при цьому - зберігаючи ясну свідомість) в нього сідає і відкриває програму.
Тепер, коли програма завантажується, дані сесії Енді потрібно прочитати зі сховища. У React хук useEffect
дозволяє виконувати функцію-коллбек при монтуванні компонента.
У коллбеці ми асинхронно отримуємо дані зі сховища, а після цього викликаємо функцію setSessionCount()
, передаючи їй ці дані, тобто - 1
:
useEffect(() => { AsyncStorage.getItem("@my_number").then(data => setSessionCount(data)) }, [])
Неспокійний Енді успішно справляється з ще однією медитацією. Тому до sessionCount
треба додати 1
, що дозволить зберегти загальне число завершених сеансів медитації.
Нове значення, як і раніше, ми записуємо в сховище:
// Користувач завершив сеанс медитації const saveData = () => { setSessionCount(prev => { const newSessionCount = prev + 1 AsyncStorage.setItem("@my_number", newSessionCount.toString()) return newSessionCount }) }
До теперішнього моменту користувач завершив 2 сеанси медитації.
День 3: Буря
Енді, тепер - уже зовсім не неспокійний, дістає телефон і відкриває застосунок для того, щоб у третє поспіль влаштувати сеанс медитації (і справи в нього йдуть добре).
Він хоче дізнатися про те, як далеко просунувся в справі вироблення корисної звички. Тому він відкриває екран статистики. «О, так тут багато всього цікавого», - примовляє він. «Відмінна програма!».
Але його любов до цієї програми швидко сходить нанівець ...
Програма повідомляє йому про те, що він провів 11 сеансів медитації. А він-то медитував всього два рази!
Неправильна статистика по сеансах медитації
Що пішло не так?
У перший день ми записали в sessionCount
початкове значення - число 0
.
Користувач завершив сеанс медитації - тому ми додали до sessionCount
- 1
. Потім ми перетворили те, що вийшло, в рядок - в «1»
, після чого записали це в асинхронне сховище (згадайте - воно може зберігати тільки строкові дані).
У другий день ми завантажуємо дані зі сховища і записуємо в sessionCount
завантажене значення. Тобто - «1»
(рядок, а не число).
Користувач завершує сеанс медитації й ми додаємо до sessionCount
1
. А в JavaScript «1» + 1
дорівнює «11»
, а не 2
.
Ми забули перетворити строкові дані зі сховища, в число.
А найгірше тут те, що наша програма при цьому не видала ніяких повідомлень про помилки. Ця помилка якийсь час залишалася непоміченою, а пізніше довела нас до неприємностей. Пошук джерел подібних проблем може виявитися не такою вже й простою справою.
JavaScript дозволив нам вільно, не усвідомлюючи того, що ми робимо, поміняти в ході виконання програми тип даних, що зберігаються в змінній.
Вирішити цю та інші подібні проблеми можна за допомогою TypeScript.
Що таке TypeScript?
Якщо ви не знайомі з TypeScript, то знайте, що це, по суті, те ж саме, що і JavaScript, але оснащене деякими корисними можливостями. Зокрема, змінні не можуть змінювати типи. А якщо це трапиться - TypeScript видасть повідомлення про помилку.
Браузери не можуть виконувати TypeScript-код. Тому TypeScript-файли проєкту треба скомпілювати в JavaScript. На виході вийде кілька JavaScript-файлів (або один великий «бандл» із JS-кодом проєкту).
Використання TypeScript в React Native-проєктах
Додати підтримку TypeScript в наявний React Native-проєкт дуже просто. А саме, треба буде дещо встановити з npm і зробити декілька налаштувань.
Далі потрібно буде лише перейменувати файли з кодом, наприклад - App.js
в App.tsx
, після чого почне працювати автоматична система контролю типів.
Після того, як змінено розширення файлу, TypeScript вибухне гнівною тирадою про те, що аргумент типу 'string | null
' не можна призначити параметру типу 'SetStateAction
'.
TypeScript попереджає розробника про те, що з типами даних щось не так
Це означає, щоб позбутися повідомлення про помилку, треба, по-перше, перевірити data
на null
, а по-друге - перетворити рядок в число (скориставшись parseInt()
):
useEffect(() => { AsyncStorage.getItem("@my_number").then(data => { if (data) { setSessionCount(parseInt(data)) } }) }, [])
Використання TypeScript підштовхує розробника до написання якіснішого та надійнішого коду. Це просто чудово!
За якими матеріалами вивчати TypeScript?
Я вивчав TypeScript по цьому відеокурсу каналу Net Ninja. І якби мені треба було б що-небудь вивчити, то я в першу чергу поцікавився б тим, чи немає на цьому каналі курсу по тому, що мені потрібно.
Крім того, офіційна документація по TypeScript дуже хороша.
Підсумки
Тепер, завдяки TypeScript, я можу спати трохи спокійніше, знаючи про те, що змінні в моєму проєкті не можуть абсолютно несподівано змінювати свої типи. Спасибі за це TypeScript.
Також не можу не відзначити, що JavaScript добре підходить для маленьких проєктів. Але при роботі над середніми та великими проєктами, а так само - над маленькими проєктами, які цілком можуть вирости, краще, мабуть, використовувати TypeScript, навіть якщо для цього доведеться витратити час на його вивчення. А якщо ви знаєте JavaScript, то і TypeScript освоїте без особливих зусиль.
Джерело: Why You Should Use TypeScript Over JavaScript in 2021 | A Simple Example
Коментарі (1)