React-query — бібліотека легкого і зручного для кешування, зберігання і управління даними в React Apps [ukr]

Презентація доповіді

Як часто ви задаєтеся питанням: як зберігати, керувати і маніпулювати даними в React Apps? Чи не хотіли б ви мати інструмент, який дозволить вам кешувати, зберігати, видаляти і підтримувати актуальними дані в реакті легко і з під коробки? Саме таким інструментом я хочу поділитись з вами на моїй доповіді. Потрібний крутий інструмент для управління данними, не хочете заморочуватись з state, context & redux. Запрошую вас поринути в світ react-query разом зі мною! Поділюсь з вами своїм особистим досвідом і скажу ЧОМУ ця бібліотека варта вашої уваги!

Лілія Карпенко
Alteryx
  • Alteryx Engineering Manager, Team Lead
  • Тім Лід, JS Розробник і Підприємниця. Віднедавна Ліля створила проєкт ScaleInIT, ціль і місія якого — розвивати і допомагати зростати будь-яким розробникам в ІТ сфері, через покращення їх Soft & Hard Skills
  • Обожнює робити те, що робить її кращою і щасливішою: навчатися новому, працювати над собою і допомагати іншим. Для Лілії важливо — свобода, справедливість, сім’я, рідні люди і насолода від процесу і життя! Вона любить досягати нових вершин, але вважає, що результат і процес однаково важливі
  • Кайфує від нового, навчання, спорту, здорової їжі, пригод і подорожей
  • Впевнена, що її життя і все, що в неї є і може бути — її особиста відповідальність. Ліля — єдиний автор свого життя і свого майбутнього
  • ЇЇ шлях — це пошук цікавих можливостей, пізнання себе і того, що навкруги. Ліля вважає, що життя треба прожити так, щоб “зверху” сказали — “А ну повтори!”
  • LinkedIn, GitHub, Instagram, Facebook

Транскрипція доповіді

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

Сьогодні я розповім про базові речі React Query, щоб ви могли ознайомитися з цією бібліотекою та зрозуміти, які можливості вона має всередині. Також я побудувала тестову аплікацію, яку ви зможете перевірити, щоб побачити, як вона працює. Я в сфері IT більше 10 років і взагалі обожнюю програмування. Це моє хобі, і я завжди відчуваю потік, коли програмую. Працюю як фронтенд-розробник, але знаю і Node.js. Я вже виступала на багатьох конференціях, таких як Odessa.js. Я також керую декількома командами та маю власний проект, де намагаюсь показати, що в IT важливі не лише хардскіли, а й софтскіли. Спорт, читання книг, танці та розвиток - ось що я люблю. Отже, сьогодні я тут, щоб представити вам React Query. Поговоримо про те, чому саме я вирішила презентувати цю бібліотеку.

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

Наприклад, коли ви працюєте навіть з React, він надає можливості для того, щоб зберігати дані, або просто в стейті, або ми можемо зберігати їх там в редакції, або у нас є контекст. Також у нас є багато інших можливостей там поза React, де ми можемо їх зберігати. Ми можемо там використовувати індекс DB, local storage і так далі. Я сьогодні якраз буду розповідати про React Query, тому що React Query може дуже допомогти вам в зберіганні даних, в тому, щоб завжди знати, що ваші дані актуальні. Вона допомагає з мемоізацією, з кешуванням, з інвалідацією старих даних. Тобто ви можете обновляти дані по тайм-ауту, ви можете рефетчити, тобто обновляти дані там, коли, наприклад, фокус зі сторінки прибирається, а потім знову приходить на сторінку. Через якісь там... Так. Інтервал, так. Тобто.

І в неї дуже класні, круті є методи для оптимізації перформанса, наприклад, такі як lazy loading, там, якщо у вас є якісь списки для infinite якогось лодінга, скролінга, також для пагінації. І сьогодні я трошечки покажу таких прикладів також на аплікації, яку я побудувала. Я сподіваюся, ви вже в захваті і вам вже дуже хочеться про неї більше дізнатись, тому давайте подивимося на якісь більш реальні приклади. Я для сьогоднішньої... презентації побудувала таку маленьку аплікацію, вона дуже проста насправді, так. Я тут навіть використала якийсь Material UI дизайн, шаблон. І суть в тому, що в нас є якийсь юзер, так, він лодіниться, потім у нас є якийсь список юзерів, ми можемо зайти на сторінку юзера. В ідеалі було б там ще, наприклад, якщо ви могли б створювати юзера, то тоді у нас би обновляли ці списки, так. Тобто для цього... Все... Про це ми будемо говорити, коли я буду показувати вам, як можна обновляти дані на сторінці. Ось. І така аплікація якраз нам потрібна для того, щоб трошки подивитися, як React Query працює.

Отже, першим ділом, що потрібно зробити для того, щоб використовувати, звичайно, React Query, нам потрібно його встановити. Там дуже проста... Базовий сетап. Нічого там такого складного немає. В принципі... З одної сторони, порог входу в React Query, він якби начебто і невеликий, але він містить в собі дуже багато нюансів. Тобто ви його можете почати використовувати там вже хоч через 10 хвилин, як закінчиться моя доповідь. Але питання в тому, що там є дуже багато нюансів, про які якраз сьогодні я хочу вам розповісти.

Отже. Першим, що мені дуже подобається і що дуже зручно, це те, що ми можемо створити... Кастомні хуки, за допомогою яких ми можемо потім, наприклад, якісь дані з нашої аплікації брати у будь-якому місці в нашому приложенні. Так? В нашій аплікації. В React Query є такий спеціальний метод, який називається Use Query. Який приймає в себе якісь там конфігурації. І одне із найголовніших, це Query ключ. І Query функція, це яка буде ці дані брати. Причому це можуть бути дані будь-звідки. Наприклад, це може бути з якогось API, або це може бути з Local Storage, можливо. У мене також будуть такі приклади трохи. Що важливо? Цей Query key, це якраз той ключ, за допомогою якого React Query кишує дані. Тобто, якщо, наприклад, ви будете потім десь в іншому місці, використовувати цей же хук з цим же Query ключем, то він не буде йти на сервер і знову запитувати ці дані, а він буде брати дані із кеша. Тобто, наприклад, тут я створила такий кастомний хук, для того, щоб мати список юзерів. Тобто, я його запитую там з якогось замоканого API. Я тут зробила також трошки оптимізацію по сторінці.

Оці Query ключі дуже гнучкі. Тобто, ми можемо використовувати їх як просто статичні, наприклад, строки. Або ми можемо тут використовувати комбінації. Наприклад, ось у мене є комбінація строки "users" і "сторінки". Тобто, це означає, що для кожної сторінки він там закишується під своїм ключем. Потім, коли я створила цей кастомний хук, я можу його дуже просто використовувати так, як тут показано, в будь-якому місці в моїй аплікації. Так? Це дуже зручно, коли він викликається вперше і бачить, що в кеші цих даних немає. Він піде, звісно, викликає query function і візьме ці дані з бекенду. А потім наступного разу, коли він побачить, наприклад, десь ще використання цього хука, він вже не буде ходити на бекенд, а просто візьме ці дані із кеша. Тобто, це дуже зручно і означає, що ви можете використовувати це в будь-якому місці.

Такі кастомні хуки можна створити безліч, так? Давайте трошки ще більш детально розглянемо те, які цікаві конфігурації можна передати всяку функцію useQuery, яку ми бачили до цього. Ми вже говорили про query function і query key. Також там є така цікава конфігурація, як enabled. Тобто, ви можете сказати, що нам потрібно завантажувати дані тільки в тому випадку, якщо, наприклад, там щось сталося. Можливо, ви там будете перевіряти, чи користувач увійшов, чи щось інше. Так. Є такі callback-функції, так? Тобто, ви можете відслідковувати, коли дані до вас приходять, чи якщо сталася якась помилка. І також є така цікава властивість, яка називається refetch interval. І цей refetch interval, якщо ви туди передасте час, наприклад, в мілісекундах 2000 (2 секунди) чи 3000 (3 секунди), то він буде кожні 3 секунди викликати запит на бекенд і оновлювати ці дані в усій вашій аплікації, де ви використовуєте цей кастомний хук useQuery. Вибачте за невірне згадування "use users". Ось. Ми ще трошки розглянемо це питання про refetch, але це такі основні базові конфігурації, які майже завжди використовуються.

Отже, що далі? В принципі, як працює кеш, давайте ще трошки поговоримо про це в React Query, оскільки це важливо. Для того щоб встановити максимальний час, наприклад, на який дані зберігаються в кеші (наприклад, 5 хвилин), ви можете змінити це, використовуючи спеціальну властивість. Зараз дайте мені секундочку. От, це вже десь тут. Отже, кеш-тайм називається. Ви можете передати це свойство кеш-тайм і сказати, наприклад, що у вас там дані в кеші будуть зберігатися, скажімо, 2-3 хвилини. Або може, наприклад, півгодини, це вже залежить від ваших потреб. Ось. І цей кеш, звісно ж, можна в якийсь момент оновлювати. Це також залежить від того, чи потрібно це вам. Які у вас є потреби. І для того, щоб оновити цей кеш, у React Query є додаткові спеціальні властивості, які дозволяють оновлювати кеш в різних випадках. Перше, про що ми вже говорили, це RefetchInterval, тобто, ви можете просто оновлювати дані через певний інтервал часу. Але важливо зауважити, що, наприклад, RefetchInterval не буде оновлювати ваші дані, якщо, наприклад, ваша вкладка не активна. Тобто, якщо, наприклад, користувач перейшов на іншу вкладку, то час там зупиняється і потім починає відраховуватися знову тоді, коли юзер заходить знову на вашу вкладку.

Якщо вам просто потрібно постійно оновлювати якісь ваші дані там протягом якогось часу, наприклад, ми в нашій аплікації використовували це для того, щоб обновляти сесію для юзера. Кожні там якісь пів години, наприклад, чи годину. І нам не потрібно чекати. Нам не важливо, так? Тобто, чи активна в нього вкладка, чи не активна. Тому ми використовували його також в комбінації з RefetchIntervalInBackground. Тому що тоді воно буде обновляти вам дані в незалежності від того, вкладка активна чи не активна на цей проміжок часу. Також ви можете встановити таке проперті як RefetchOnMount в True. Тоді у вас при кожному маунті будуть взагалі обновлятися дані. Але тут бути дуже обережними, тому що це тоді насправді майже знівелює, мені здається, всю, як би, логіку і позитивні моменти від того, що у вас взагалі є кеш. Тому дійсно прокидуйте його в True тільки тоді, коли вам це дійсно потрібно.

Ось. Також можна ще зробити, наприклад, RefetchOnWindowFocus. Тобто, коли ви, повернулися на вкладку, повернулися на компонент, то можливо на неї зробили якийсь фокус і тоді можна там дані обновити. Ну, взагалі це дуже круто, дуже багато цікавих можливостей можна використовувати завдяки таким конфігам. От. Отже. Що тепер? Хотіла також показати такий простий приклад. Наприклад, якщо ми хочемо в якийсь момент у нас є, наприклад, список юзерів і, допустимо, ми там додаємо нового юзера або видаляємо існуючого. Це означає, що нам потрібно, крім того, що ми там будемо на бекенд відправляти дані так і зберігати їх там, ми потрібні локально у себе дані обновити і сказати, що от ці дані, так, вони вже невалідні. Для цього в UseQuery існує такий об'єкт, який називається QueryClient і він в собі містить такий метод, який називається InvalidateQueries.

Цей метод якраз потрібний для того, щоб в якийсь момент, наприклад, при додаванні нового юзера, видаленні, так, або як редагуванні, щоб в цей момент ми могли сказати, що ці дані вже невалідні. Ви, будь ласка, обновіть мені ці дані, вже не обновляйте ці дані в кеші. І для цього використовується якраз цей метод InvalidateQueries. Я в своїй аплікації, наприклад, створила, я зберігаю юзера залогіненого в LocalStorage і, наприклад, коли я логінюся, ті дані туди закидую і також я зберігаю ці дані також в кеші ще в LocalStorage. Тому в якийсь момент, наприклад, коли я там буду, я буду показувати вам зараз аплікацію, там буде трошки зрозуміліше, тобто я хочу вилогінити юзера, то я буду робити InvalidateQueries і воно мені видалить всі дані і знову візме їх з того місця, де я сказала йому їх взяти, тобто там, де я оказала цю Query Function, а я говорила там, що мені потрібно взяти ці дані, буде із LocalStorage.

Це, до речі, один із прикладів. Я тут встановила RefetchInterval на 2 секунди, тобто кожні 2 секунди перевіряю, чи є в мене ще дані в LocalStorage про користувача, і якщо їх там немає, то тоді на... OnError я тут встановила, воно буде на логін редиректити, тобто користувача, скоріше за все, вже немає, не існує, він там, можливо, заекспайрився чи ще щось. Ось. Наступний приклад. Це про оптимізацію саме за допомогою таких методів, як пагінація. Тобто я, як я вже казала, можу передавати в QueryKey будь-яку комбінацію строк, чисел. У даному випадку я тут кажу, що я хочу, щоб це було query для користувача, для користувачів, коли ми отримуємо список, щоб він в кеші зберігав саме по сторінкам ці дані, так. І таким чином ми, як би, оптимізуємо запити, тому що якщо воно вже бачить, що в кеші є з такою сторінкою, наприклад, дані для користувача, то воно не буде робити знову запит. Дуже прикольно, і у QueryClient також... Існує, ну, взагалі, у React Query існує такий метод, який називається prefetch query. І за допомогою нього ви, наприклад, можете запитати якісь дані наперед, наприклад, якщо у вас там є таблиця або, можливо, там якийсь список, так, і ви не хочете, щоб користувач чекав, поки там загрузиться друга сторінка, тому що там, можливо, довго щось відповідає.

Ви можете за допомогою prefetch query запитати дані на наступну сторінку, на наступні, можливо, там декілька сторінок. І воно потім, якщо ви використаєте цей prefetch query, при наступному запиті на query function воно побачить і подивиться спочатку в кеш, і якщо воно знайде в кеші дані, то воно не буде робити запит на бекенд відповідно, чи там на ту query function, яку ви вказали. Тобто за допомогою цього ви можете дійсно покращити такий UI для користувачів, щоб вони не чекали відповіді і щоб вони просто побачили одразу класний якийсь UI. Отже, я сподіваюся, що все зрозуміло. Якщо не зрозуміло – це все не страшно, тепер ви хоча б чуєте про те, що таке існує, і ви зможете потім зайти і все почитати в документації, або запитати в Discord мене трошки пізніше. Тоді давайте проговоримо ще про таке як мутації.

Отже, в React Query існує така річ, яка називається мутації. І це потрібно нам якраз для того, щоб якось змінювати ті дані, які у нас вже є. Наприклад, у нас є список користувачів, і той приклад, який ми вже брали, що ми додаємо користувача, видаляємо його, наприклад, то в такому випадку ми будемо, скоріше за все, відправляти якийсь запит на бекенд, наприклад, так, оновлювати ці дані. І після того, як ми, наприклад, додали чи видалили користувача, нам потрібно буде ці дані оновити в себе локально, в кеші. І тому для цього існують такі штуки, як мутації. Вони можуть використовуватися за допомогою метода useMutations, useMutation, який є в React Query. І ви можете туди передати mutation function, якраз те, що потрібно зробити, для того, щоб дані оновити, і потім, якщо ви побачите, що у вас відповідь позитивна, наприклад, від сервера, ви можете очистити кеш, і дані автоматично запитаються знову і оновляться в вашому кеші.

Тут я в Query Key передала просто ключ users без сторінок, тому що, якщо, наприклад, я додаю нового користувача, я не знаю, на яку сторінку він потрапляє, звичайно, так, тому що це може бути якесь рутування, там, можливо, по імені, там, чи по чомусь, тому я просто інвалідую всі, весь кеш по користувачах. Це можна зробити також просто так. Якщо у нас був такий комбінований ключ, як з користувачем і зі сторінкою, коли я інвалідую, я просто інвалідую всіх користувачів, і таким чином у нас кеш оновлюється, і все дуже зручно, і всі дані, де потрібно, оновилися, і вони up-to-date. Отже, що ще такого крутого є в React Query, на що можна подивитися, і що можна використовувати? По-перше, є Infinite Queries, так? Якщо у вас є якісь безкінечні списки, ви можете використовувати спеціальний метод в React Query, який називається Use Infinite Query, здається, і він якраз там дає вам логіку для того, щоб працювати з такими запитами на якийсь безкінечний список, наприклад.

Ви можете, наприклад, використовувати такі фічі, як пауза, тобто ви можете в який-то момент, наприклад, сказати, що зараз ми не будемо запитувати дані по якомусь там ключу, так? Також вони мають фічу для саспенс, тобто ви можете використовувати реактивний саспенс, і в комбінації з React Query ви можете там прописувати fallback, можливо, там потрібно якісь додаткові дані взяти в момент цього fallback. І одне із таких, мені здається, дуже крутих штук, яких в них є, це persistent storages. Я не робила приклада по persistent storages, але трошки хотіла просто детальніше показати, як саме це працює і в чому взагалі суть, і яка тут є, якась прикольна фішка. Насправді цей persister дозволяє вам, по суті, крім того, що React Query зберігає свої дані в кеші, які ви можете, звісно, брати з цього кешу, ви можете також, наприклад, сказати, що вам потрібно здублювати і зберігати ці дані ще в якомусь іншому місці.

Наприклад, можливо, там в Local Storage, або там, можливо, в IndexDB. Я для цього прикладу вибрала Local Storage. Для чого це потрібно? Ну, наприклад, якщо у вас є мобільна аплікація, або взагалі просто ваша аплікація, вона повинна завжди мати дані, і якщо, наприклад, ви виходите офлайн, ви все одно хочете працювати з даними, то такий persister може якраз використовуватись для того, щоб ви могли ці дані, наприклад, якщо ви офлайн, зберігати в Local Storage, а потім, якщо ви знову, наприклад, з'являєтеся онлайн, ви ці дані потім можете відправити на бекенд, куди потрібно, і вони будуть актуальними, і користувач зможе працювати з вашою аплікацією навіть тоді, коли ви офлайн. І там, насправді, сетап взагалі не дуже важкий. Вони там все зробили майже під капотом.

Можливо, тільки потрібно буде зробити оцю логіку, коли ви переключаєтесь з офлайна на онлайн. Наприклад, як там ці дані правильно перекинути, як їх відправити і так далі. Отже, це, в принципі, все, що я хотіла розповісти про React Query. Давайте тоді трошки ще детальніше подивимося на аплікацію, яку я створила, і я вам трошки покажу, що я маю на увазі, коли я говорю про кеш в React Query, і як подивимося, що саме я говорю, коли воно не робить додаткові запити, як ми можемо ці дані використовувати потім. Отже, що у мене є? У мене є звичайна аплікація, логін-сторінка, після чого, після входу, у мене є список користувачів, і після того, як я роблю вхід, коли мене перекидає на список користувачів, у мене також є детальна сторінка для користувача, де я показую просто базову інформацію про цього користувача, і на сторінці users я використовую цей хук, який я показувала вам, useUsers, я сподіваюся, що видно, хоча б не дуже мілкий шрифт, якщо чесно. Я так і подумала, щось, а як би це зробити? О, ресурс. О, кайф, працює. Так, ну, тобто, в принципі, теоретично, тут не так, щоб дуже треба дивитися на код, просто в цьому суть, що у нас є цей хук useUsers, який я показувала вам, який запитує дані у бекенда, так. І у мене цей useUsers також використовується в багатьох місцях, наприклад, у мене є просто сторінка користувачів, це ось ця сторінка, потім у мене є ще окрема компонента, яка саме відображає список цих користувачів, називається вона в мене usersList, дуже оригінально.

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

Звичайно, коли ми там вже переходимо, наприклад, по сторінкам, то воно вже там робить потім запити, робить потім запити знову, тому що це робить, він, основний запит, але, наприклад, взагалі, тобто, воно бере ці дані із кешу, якщо вони там є. Також, наприклад, в мене от на цю кнопку "Refresh User Data", я роблю просто invalidateQueries. Тут в мене є кнопочка, називається вона "Refresh User Data", я тут просто роблю invalidateQueries, тобто, роблю, як би, видаляю дані, і кажу, що вони вже не актуальні. І після того, як я на це нажимаю, то воно виходить, знову запитуються дані на бекенді і обновляються дані. В принципі, все. Також там у мене ще запитуються поточний, юзер. Це в мене є хук, який називається useCurrentUser, який робить refetchInterval. В принципі, якщо захочете, то можна зробити консоль log, і ми побачимо, що воно... Робить запити там кожні 2 секунди.

От, тобто, воно запитується дані кожні 2 секунди. От, в принципі, все. І на логаут я видаляю дані із local storage. Зараз в мене там є якийсь токен про юзера лежить, потім я його видаляю і воно мене вилогінює. В принципі, це все. Я сподіваюсь, вам було корисно. Я сподіваюсь, ви цю бібліотеку будете використовувати, або хоча б подивитись на неї і запропонуєте її в своїх проектах. Тому що, насправді, вона дає нам дуже багато всього крутого. Ми дійсно використовуємо всі її фішки кешування і оці всі різні таймаути, refetch інтервали. І це дуже зручно. Не потрібно робити нічого додатково. Все є з-під капота. В них, до речі, дуже класне там нове оновлення вийшло. Тому вона активно розвивається, що також дуже, мені здається, важливо, так, для... бібліотек, в принципі. Дуже рекомендую використовувати її. Я була сьогодні дуже рада вам презентувати свій проект. Я сподіваюсь, ви винесли для себе багато цього цікавого. В принципі, підписуйтесь на мене в соціальних мережах. Я зараз активно в інстаграмі знаходжусь. І також лінк, напевно, на той проект, який я створила, я зараз скину в загальному чаті.

Увійти
Або поштою
Увійти
Або поштою
Реєстрація через e-mail
Реєстрація через e-mail
Забули пароль?