Стендап Сьогодні 📢 Канал в Telegram @stendap_sogodni

🤖🚫 AI-free content. This post is 100% written by a human, as is everything on my blog. Enjoy!

08.01.2023

Як я будую структури даних додатків на React за допомогою reselect

Сьогодні день Сінтри; просуваюсь до розділу “Ціли та накопичення”. Доречно буде розказати про мою улюблену схему організації потоку даних для React/Redux.

Я звик розташовувати у Redux дані у найбільш спрощеній формі. (Частково тому, що я віддаю перевагу архітектурі без бекенду, тому не маю можливості перенести логіку туди, щоб отримувати більш підготовані дані.) Далі всі форми, що необхідні для відображення компонент, створюються шаром селекторів, тобто функцій, що отримують на вхід стан Redux та повертають те, що потрібно. Компонентам залишається підписатись на результати селекторів хуком useSelector.

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

Другий — селектори reselect. Їхній результат кешується, але дещо нетривіально. Функція-селектор будується з функцій підготовки аргументів, та “робочої” функції, що обчислює результат. Поки аргументи не змінюються, “робоча” функція не буде викликана. Так, наприклад, можна побудувати селектор, що буде підраховувати загальну суму витрат — але тільки тоді, коли у стані змінюються витрати.

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

Але з селекторами, що повертають складні обʼєкти, є проблема: згенерований ними результат буде змінюватись за посиланням навіть коли він залишається сталим за значенням. У такому випадку всі залежні селектори та компоненти будуть перераховані зайвий раз. Ну, наприклад: в мене є селектор, що з масиву цілей робить обʼєкт-словник, проіндексований за ID. Він лежить в основі багатьох інших селекторів. Всі вони будуть перераховані кожний раз, коли є зміни в будь-якому місці вхідного масиву. Саме через такі марні витрати й починають гальмувати додатки на React. Я про це писав цілу статтю, висновок якої — що треба для таких випадків використовувати стабільні селектори, які додатково перевіряють, чи змінився обʼєкт за значенням.

Всі три різновиди селекторів мають інтерфейс звичайної функції, та є взаємозамінними, тому їх легко рефакторити або додавати нові.

До речі, саме таку архітектуру рекомендує сучасний Redux.