[{"data":1,"prerenderedAt":35940},["ShallowReactive",2],{"navigation_docs":3,"-react-native-version2-rtk-query-mobile":3728,"-react-native-version2-rtk-query-mobile-surround":35935},[4,1707,1912,2366,2547,2673,2880,3002,3052,3109,3143,3269,3346,3360,3495,3512,3525,3671,3724],{"title":5,"icon":6,"path":7,"stem":8,"children":9},"C#","i-devicon-csharp","\u002Fcsharp","01.csharp",[10,13,60,90,120,202,219,253,379,404,457,650,1364,1654,1703],{"title":11,"path":7,"stem":12},"C# та .NET","01.csharp\u002Findex",{"title":14,"icon":15,"path":16,"stem":17,"children":18,"page":59},"Fundamentals","i-lucide-book-open","\u002Fcsharp\u002Ffundamentals","01.csharp\u002F01.fundamentals",[19,23,27,31,35,39,43,47,51,55],{"title":20,"path":21,"stem":22},"Вступ до екосистеми .NET","\u002Fcsharp\u002Ffundamentals\u002Fintroduction-to-ecosystem","01.csharp\u002F01.fundamentals\u002F01.introduction-to-ecosystem",{"title":24,"path":25,"stem":26},"Структура програми на C#","\u002Fcsharp\u002Ffundamentals\u002Fprogram-structure","01.csharp\u002F01.fundamentals\u002F02.program-structure",{"title":28,"path":29,"stem":30},"Змінні та Типи Даних","\u002Fcsharp\u002Ffundamentals\u002Fvariables-data-types","01.csharp\u002F01.fundamentals\u002F03.variables-data-types",{"title":32,"path":33,"stem":34},"Масиви","\u002Fcsharp\u002Ffundamentals\u002Farrays","01.csharp\u002F01.fundamentals\u002F04.arrays",{"title":36,"path":37,"stem":38},"Strings & Text Handling","\u002Fcsharp\u002Ffundamentals\u002Fstrings-text-handling","01.csharp\u002F01.fundamentals\u002F05.strings-text-handling",{"title":40,"path":41,"stem":42},"Дати і Час","\u002Fcsharp\u002Ffundamentals\u002Fdates-time-handling","01.csharp\u002F01.fundamentals\u002F06.dates-time-handling",{"title":44,"path":45,"stem":46},"Потік Керування","\u002Fcsharp\u002Ffundamentals\u002Fcontrol-flow","01.csharp\u002F01.fundamentals\u002F07.control-flow",{"title":48,"path":49,"stem":50},"Методи","\u002Fcsharp\u002Ffundamentals\u002Fmethods","01.csharp\u002F01.fundamentals\u002F08.methods",{"title":52,"path":53,"stem":54},"Основи Відлагодження","\u002Fcsharp\u002Ffundamentals\u002Fdebugging-basics","01.csharp\u002F01.fundamentals\u002F09.debugging-basics",{"title":56,"path":57,"stem":58},"Інтерактивна Консоль (Classic)","\u002Fcsharp\u002Ffundamentals\u002Finteractive-console","01.csharp\u002F01.fundamentals\u002F10.interactive-console",false,{"title":61,"icon":62,"path":63,"stem":64,"children":65,"page":59},"OOP","i-lucide-box","\u002Fcsharp\u002Foop","01.csharp\u002F02.oop",[66,70,74,78,82,86],{"title":67,"path":68,"stem":69},"Package Management (Управління Пакетами)","\u002Fcsharp\u002Foop\u002Fpackage-management","01.csharp\u002F02.oop\u002F01.package-management",{"title":71,"path":72,"stem":73},"Класи та Об'єкти","\u002Fcsharp\u002Foop\u002Fclasses-objects","01.csharp\u002F02.oop\u002F02.classes-objects",{"title":75,"path":76,"stem":77},"Властивості та Поля","\u002Fcsharp\u002Foop\u002Fproperties-fields","01.csharp\u002F02.oop\u002F03.properties-fields",{"title":79,"path":80,"stem":81},"Стовпи ООП","\u002Fcsharp\u002Foop\u002Foop-pillars","01.csharp\u002F02.oop\u002F04.oop-pillars",{"title":83,"path":84,"stem":85},"Advanced Types","\u002Fcsharp\u002Foop\u002Fadvanced-types","01.csharp\u002F02.oop\u002F05.advanced-types",{"title":87,"path":88,"stem":89},"Namespaces (Простори Імен)","\u002Fcsharp\u002Foop\u002Fnamespaces","01.csharp\u002F02.oop\u002F06.namespaces",{"title":91,"icon":92,"path":93,"stem":94,"children":95,"page":59},"Advanced Core","i-lucide-zap","\u002Fcsharp\u002Fadvanced-core","01.csharp\u002F03.advanced-core",[96,100,104,108,112,116],{"title":97,"path":98,"stem":99},"Generics (Узагальнення)","\u002Fcsharp\u002Fadvanced-core\u002Fgenerics","01.csharp\u002F03.advanced-core\u002F01.generics",{"title":101,"path":102,"stem":103},"Делегати, Події та Лямбда-вирази","\u002Fcsharp\u002Fadvanced-core\u002Fdelegates-events-lambdas","01.csharp\u002F03.advanced-core\u002F02.delegates-events-lambdas",{"title":105,"path":106,"stem":107},"Interfaces Deep Dive (Інтерфейси: Поглиблений Розгляд)","\u002Fcsharp\u002Fadvanced-core\u002Finterfaces-deep-dive","01.csharp\u002F03.advanced-core\u002F03.interfaces-deep-dive",{"title":109,"path":110,"stem":111},"Обробка Винятків","\u002Fcsharp\u002Fadvanced-core\u002Fexception-handling","01.csharp\u002F03.advanced-core\u002F04.exception-handling",{"title":113,"path":114,"stem":115},"Pattern Matching","\u002Fcsharp\u002Fadvanced-core\u002Fpattern-matching","01.csharp\u002F03.advanced-core\u002F05.pattern-matching",{"title":117,"path":118,"stem":119},"Додаткові Можливості C#","\u002Fcsharp\u002Fadvanced-core\u002Fadditional-features","01.csharp\u002F03.advanced-core\u002F06.additional-features",{"title":121,"icon":122,"path":123,"stem":124,"children":125,"page":59},"Architecture Best Practices","i-lucide-building-2","\u002Fcsharp\u002Farchitecture-best-practices","01.csharp\u002F04.architecture-best-practices",[126,130,149,153,157,161,165,169],{"title":127,"path":128,"stem":129},"Software Design Principles (Частина 1)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fsoftware-design-principles","01.csharp\u002F04.architecture-best-practices\u002F01.software-design-principles",{"title":131,"icon":132,"path":133,"stem":134,"children":135,"page":59},"Design Patterns","i-lucide-folder","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdesign-patterns","01.csharp\u002F04.architecture-best-practices\u002F02.design-patterns",[136],{"title":137,"icon":132,"path":138,"stem":139,"children":140,"page":59},"Creational","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdesign-patterns\u002Fcreational","01.csharp\u002F04.architecture-best-practices\u002F02.design-patterns\u002Fcreational",[141,145],{"title":142,"path":143,"stem":144},"Singleton (Одинак)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdesign-patterns\u002Fcreational\u002Fsingleton","01.csharp\u002F04.architecture-best-practices\u002F02.design-patterns\u002Fcreational\u002F01.singleton",{"title":146,"path":147,"stem":148},"Builder (Будівельник)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdesign-patterns\u002Fcreational\u002Fbuilder","01.csharp\u002F04.architecture-best-practices\u002F02.design-patterns\u002Fcreational\u002F02.builder",{"title":150,"path":151,"stem":152},"Building Professional CLIs","\u002Fcsharp\u002Farchitecture-best-practices\u002Fbuilding-professional-clis","01.csharp\u002F04.architecture-best-practices\u002F03.building-professional-clis",{"title":154,"path":155,"stem":156},"Validation & Flow Control","\u002Fcsharp\u002Farchitecture-best-practices\u002Fvalidation-flow-control","01.csharp\u002F04.architecture-best-practices\u002F04.validation-flow-control",{"title":158,"path":159,"stem":160},"The Modern .NET Host (Microsoft.Extensions)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fmodern-dotnet-host","01.csharp\u002F04.architecture-best-practices\u002F05.modern-dotnet-host",{"title":162,"path":163,"stem":164},"Data Mapper: Repository та DAO патерни (Частина 1)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdata-mapper-part1","01.csharp\u002F04.architecture-best-practices\u002F06.data-mapper-part1",{"title":166,"path":167,"stem":168},"Data Mapper: Repository та DAO патерни (Частина 2)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdata-mapper-part2","01.csharp\u002F04.architecture-best-practices\u002F07.data-mapper-part2",{"title":170,"icon":132,"path":171,"stem":172,"children":173,"page":59},"Di Ioc","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc",[174,178,182,186,190,194,198],{"title":175,"path":176,"stem":177},"Проблема залежностей та Інверсія Контролю","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fthe-dependency-problem","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F01.the-dependency-problem",{"title":179,"path":180,"stem":181},"Будуємо власний Service Container","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fbuild-your-own-container","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F02.build-your-own-container",{"title":183,"path":184,"stem":185},"Service Locator: Паттерн та Анти-паттерн","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fservice-locator-pattern","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F03.service-locator-pattern",{"title":187,"path":188,"stem":189},"Паттерни Dependency Injection","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fdependency-injection-patterns","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F04.dependency-injection-patterns",{"title":191,"path":192,"stem":193},"Microsoft DI: IServiceCollection та IServiceProvider","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fmicrosoft-di-deep-dive","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F05.microsoft-di-deep-dive",{"title":195,"path":196,"stem":197},"Service Lifetimes та Scopes","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fservice-lifetimes-and-scopes","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F06.service-lifetimes-and-scopes",{"title":199,"path":200,"stem":201},"DI Анти-паттерни та Найкращі Практики","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fdi-anti-patterns-and-best-practices","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F07.di-anti-patterns-and-best-practices",{"title":203,"icon":132,"path":204,"stem":205,"children":206,"page":59},"Standard Library","\u002Fcsharp\u002Fstandard-library","01.csharp\u002F05.standard-library",[207,211,215],{"title":208,"path":209,"stem":210},"Collections (Колекції)","\u002Fcsharp\u002Fstandard-library\u002Fcollections","01.csharp\u002F05.standard-library\u002F01.collections",{"title":212,"path":213,"stem":214},"High Performance Types (Високопродуктивні Типи)","\u002Fcsharp\u002Fstandard-library\u002Fhigh-performance-types","01.csharp\u002F05.standard-library\u002F02.high-performance-types",{"title":216,"path":217,"stem":218},"LINQ (Language Integrated Query)","\u002Fcsharp\u002Fstandard-library\u002Flinq","01.csharp\u002F05.standard-library\u002F03.linq",{"title":220,"icon":221,"path":222,"stem":223,"children":224,"page":59},"System Internals Concurrency","i-lucide-server","\u002Fcsharp\u002Fsystem-internals-concurrency","01.csharp\u002F06.system-internals-concurrency",[225,229,233,237,241,245,249],{"title":226,"path":227,"stem":228},"Memory Management","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fmemory-management","01.csharp\u002F06.system-internals-concurrency\u002F01.memory-management",{"title":230,"path":231,"stem":232},"Reflection API: System.Type та Метадані","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Freflection-fundamentals","01.csharp\u002F06.system-internals-concurrency\u002F02.reflection-fundamentals",{"title":234,"path":235,"stem":236},"Attributes та Dynamic Language Runtime","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fattributes-dynamic","01.csharp\u002F06.system-internals-concurrency\u002F03.attributes-dynamic",{"title":238,"path":239,"stem":240},"Expression Trees: Швидка Альтернатива Рефлексії","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fexpression-trees-compiled","01.csharp\u002F06.system-internals-concurrency\u002F04.expression-trees-compiled",{"title":242,"path":243,"stem":244},"Source Generators: Compile-Time Code Generation","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fsource-generators","01.csharp\u002F06.system-internals-concurrency\u002F05.source-generators",{"title":246,"path":247,"stem":248},"Multithreading Fundamentals","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fmultithreading-fundamentals","01.csharp\u002F06.system-internals-concurrency\u002F06.multithreading-fundamentals",{"title":250,"path":251,"stem":252},"Synchronization Primitives","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fsynchronization-primitives","01.csharp\u002F06.system-internals-concurrency\u002F07.synchronization-primitives",{"title":254,"icon":255,"path":256,"stem":257,"children":258,"page":59},"System Programming Windows","i-lucide-cpu","\u002Fcsharp\u002Fsystem-programming-windows","01.csharp\u002F07.system-programming-windows",[259,263,267,271,275,279,283,287,291,295,299,303,307,311,315,319,323,327,331,335,339,343,347,351,355,359,363,367,371,375],{"title":260,"path":261,"stem":262},"Як Працює Операційна Система","\u002Fcsharp\u002Fsystem-programming-windows\u002Fhow-os-works","01.csharp\u002F07.system-programming-windows\u002F01.how-os-works",{"title":264,"path":265,"stem":266},"Процеси в .NET — API та Запуск","\u002Fcsharp\u002Fsystem-programming-windows\u002Fprocesses-in-dotnet","01.csharp\u002F07.system-programming-windows\u002F02.processes-in-dotnet",{"title":268,"path":269,"stem":270},"Процеси в .NET — IPC та Міжпроцесна Комунікація","\u002Fcsharp\u002Fsystem-programming-windows\u002F02a.processes-ipc","01.csharp\u002F07.system-programming-windows\u002F02a.processes-ipc",{"title":272,"path":273,"stem":274},"Application Domains та Збірки — AppDomain і AssemblyLoadContext","\u002Fcsharp\u002Fsystem-programming-windows\u002Fappdomains-assemblies","01.csharp\u002F07.system-programming-windows\u002F03.appdomains-assemblies",{"title":276,"path":277,"stem":278},"Application Domains та Збірки — Plug-in Система з Hot-Reload","\u002Fcsharp\u002Fsystem-programming-windows\u002F03a.appdomains-plugin-system","01.csharp\u002F07.system-programming-windows\u002F03a.appdomains-plugin-system",{"title":280,"path":281,"stem":282},"Потоки — Основи та API Thread","\u002Fcsharp\u002Fsystem-programming-windows\u002Fthread-fundamentals","01.csharp\u002F07.system-programming-windows\u002F04.thread-fundamentals",{"title":284,"path":285,"stem":286},"Потоки — Lifecycle, Пріоритети та Безпечне Завершення","\u002Fcsharp\u002Fsystem-programming-windows\u002F04a.thread-lifecycle-priorities","01.csharp\u002F07.system-programming-windows\u002F04a.thread-lifecycle-priorities",{"title":288,"path":289,"stem":290},"Проблеми Спільного Стану — Race Condition та Data Race","\u002Fcsharp\u002Fsystem-programming-windows\u002Fshared-state-problems","01.csharp\u002F07.system-programming-windows\u002F05.shared-state-problems",{"title":292,"path":293,"stem":294},"Проблеми Спільного Стану — Memory Model та volatile","\u002Fcsharp\u002Fsystem-programming-windows\u002F05a.shared-state-memory-model","01.csharp\u002F07.system-programming-windows\u002F05a.shared-state-memory-model",{"title":296,"path":297,"stem":298},"Синхронізація — Monitor, lock та еволюція примітивів","\u002Fcsharp\u002Fsystem-programming-windows\u002Fsynchronization-fundamentals","01.csharp\u002F07.system-programming-windows\u002F06.synchronization-fundamentals",{"title":300,"path":301,"stem":302},"Синхронізація — Наскрізний Приклад та Deadlock Detection","\u002Fcsharp\u002Fsystem-programming-windows\u002F06a.synchronization-walkthrough","01.csharp\u002F07.system-programming-windows\u002F06a.synchronization-walkthrough",{"title":304,"path":305,"stem":306},"Синхронізація — Mutex, Semaphore та Event-Based Primitives","\u002Fcsharp\u002Fsystem-programming-windows\u002Fsynchronization-advanced","01.csharp\u002F07.system-programming-windows\u002F07.synchronization-advanced",{"title":308,"path":309,"stem":310},"Синхронізація — Interlocked, Volatile та Lock-Free Структури","\u002Fcsharp\u002Fsystem-programming-windows\u002F07a.synchronization-advanced-walkthrough","01.csharp\u002F07.system-programming-windows\u002F07a.synchronization-advanced-walkthrough",{"title":312,"path":313,"stem":314},"Interlocked, CAS та Lock-Free Структури","\u002Fcsharp\u002Fsystem-programming-windows\u002Finterlocked-cas-lockfree","01.csharp\u002F07.system-programming-windows\u002F08.interlocked-cas-lockfree",{"title":316,"path":317,"stem":318},"Volatile, Memory Model та Spinning","\u002Fcsharp\u002Fsystem-programming-windows\u002F08a.volatile-memory-model","01.csharp\u002F07.system-programming-windows\u002F08a.volatile-memory-model",{"title":320,"path":321,"stem":322},"ThreadPool — Пул Потоків для Ефективного Виконання","\u002Fcsharp\u002Fsystem-programming-windows\u002Fthread-pool","01.csharp\u002F07.system-programming-windows\u002F09.thread-pool",{"title":324,"path":325,"stem":326},"ThreadPool — Просунуті Сценарії та Внутрішня Будова","\u002Fcsharp\u002Fsystem-programming-windows\u002F09a.thread-pool-advanced","01.csharp\u002F07.system-programming-windows\u002F09a.thread-pool-advanced",{"title":328,"path":329,"stem":330},"Concurrent та Immutable Collections","\u002Fcsharp\u002Fsystem-programming-windows\u002Fconcurrent-collections","01.csharp\u002F07.system-programming-windows\u002F10.concurrent-collections",{"title":332,"path":333,"stem":334},"TPL, Task та Композиція — Від Thread до Task","\u002Fcsharp\u002Fsystem-programming-windows\u002Ftpl-parallel-plinq","01.csharp\u002F07.system-programming-windows\u002F11.tpl-parallel-plinq",{"title":336,"path":337,"stem":338},"Parallel Class та PLINQ — Data Parallelism","\u002Fcsharp\u002Fsystem-programming-windows\u002F11a.tpl-parallel-plinq-advanced","01.csharp\u002F07.system-programming-windows\u002F11a.tpl-parallel-plinq-advanced",{"title":340,"path":341,"stem":342},"Async\u002FAwait — Фундамент Асинхронного Програмування","\u002Fcsharp\u002Fsystem-programming-windows\u002Fasync-fundamentals","01.csharp\u002F07.system-programming-windows\u002F12.async-fundamentals",{"title":344,"path":345,"stem":346},"SynchronizationContext та ConfigureAwait — Контекст Виконання","\u002Fcsharp\u002Fsystem-programming-windows\u002Fasync-context-configureawait","01.csharp\u002F07.system-programming-windows\u002F13.async-context-configureawait",{"title":348,"path":349,"stem":350},"Async — Просунуті Паттерни","\u002Fcsharp\u002Fsystem-programming-windows\u002Fasync-advanced","01.csharp\u002F07.system-programming-windows\u002F14.async-advanced",{"title":352,"path":353,"stem":354},"System.Threading.Channels — Async Producer-Consumer","\u002Fcsharp\u002Fsystem-programming-windows\u002Fchannels","01.csharp\u002F07.system-programming-windows\u002F15.channels",{"title":356,"path":357,"stem":358},"Асинхронна Синхронізація","\u002Fcsharp\u002Fsystem-programming-windows\u002Fasync-synchronization","01.csharp\u002F07.system-programming-windows\u002F16.async-synchronization",{"title":360,"path":361,"stem":362},"Unsafe Code та Вказівники","\u002Fcsharp\u002Fsystem-programming-windows\u002Funsafe-code","01.csharp\u002F07.system-programming-windows\u002F17.unsafe-code",{"title":364,"path":365,"stem":366},"P\u002FInvoke та Windows API — Міст між .NET та Native Code","\u002Fcsharp\u002Fsystem-programming-windows\u002Fpinvoke-winapi","01.csharp\u002F07.system-programming-windows\u002F18.pinvoke-winapi",{"title":368,"path":369,"stem":370},"Реєстр Windows — Центральна База Конфігурації Системи","\u002Fcsharp\u002Fsystem-programming-windows\u002Fwindows-registry","01.csharp\u002F07.system-programming-windows\u002F19.windows-registry",{"title":372,"path":373,"stem":374},"Windows Hooks, Hotkeys та Services — Глибока Інтеграція з ОС","\u002Fcsharp\u002Fsystem-programming-windows\u002Fwindows-hooks-services","01.csharp\u002F07.system-programming-windows\u002F20.windows-hooks-services",{"title":376,"path":377,"stem":378},"Системне Програмування C# (Windows) — 07.system-programming-windows","\u002Fcsharp\u002Fsystem-programming-windows\u002Fimplementation_plan","01.csharp\u002F07.system-programming-windows\u002Fimplementation_plan",{"title":380,"icon":132,"path":381,"stem":382,"children":383,"page":59},"Io","\u002Fcsharp\u002Fio","01.csharp\u002F08.io",[384,388,392,396,400],{"title":385,"path":386,"stem":387},"8.1.1. Основи роботи з файловою системою","\u002Fcsharp\u002Fio\u002Ffile-system-basics","01.csharp\u002F08.io\u002F01.file-system-basics",{"title":389,"path":390,"stem":391},"8.1.2. Потоки (Streams) та Серіалізація Даних","\u002Fcsharp\u002Fio\u002Fstreams-serialization","01.csharp\u002F08.io\u002F02.streams-serialization",{"title":393,"path":394,"stem":395},"8.2.1. JSON Serialization з System.Text.Json","\u002Fcsharp\u002Fio\u002Fjson-serialization","01.csharp\u002F08.io\u002F03.json-serialization",{"title":397,"path":398,"stem":399},"8.2.2. XML Serialization та LINQ to XML","\u002Fcsharp\u002Fio\u002Fxml-serialization","01.csharp\u002F08.io\u002F04.xml-serialization",{"title":401,"path":402,"stem":403},"8.2.3. Binary Serialization: MessagePack та Protocol Buffers","\u002Fcsharp\u002Fio\u002Fbinary-serialization","01.csharp\u002F08.io\u002F05.binary-serialization",{"title":405,"icon":132,"path":406,"stem":407,"children":408,"page":59},"Ado Net","\u002Fcsharp\u002Fado-net","01.csharp\u002F09.ado-net",[409,413,417,421,425,429,433,437,441,445,449,453],{"title":410,"path":411,"stem":412},"9.1. Введення в ADO.NET","\u002Fcsharp\u002Fado-net\u002Fintroduction-to-adonet","01.csharp\u002F09.ado-net\u002F01.introduction-to-adonet",{"title":414,"path":415,"stem":416},"9.2. Клас DbConnection — з'єднання з базою даних","\u002Fcsharp\u002Fado-net\u002Fconnection","01.csharp\u002F09.ado-net\u002F02.connection",{"title":418,"path":419,"stem":420},"9.3. Клас DbCommand — виконання SQL-запитів","\u002Fcsharp\u002Fado-net\u002Fcommand-and-queries","01.csharp\u002F09.ado-net\u002F03.command-and-queries",{"title":422,"path":423,"stem":424},"9.4. Клас DbDataReader — ефективне читання даних","\u002Fcsharp\u002Fado-net\u002Fdatareader","01.csharp\u002F09.ado-net\u002F04.datareader",{"title":426,"path":427,"stem":428},"9.5. Параметризовані запити та захист від SQL Injection","\u002Fcsharp\u002Fado-net\u002Fparameters-and-sql-injection","01.csharp\u002F09.ado-net\u002F05.parameters-and-sql-injection",{"title":430,"path":431,"stem":432},"9.6. Транзакції в ADO.NET","\u002Fcsharp\u002Fado-net\u002Ftransactions","01.csharp\u002F09.ado-net\u002F06.transactions",{"title":434,"path":435,"stem":436},"9.7. DbProviderFactory — провайдер-незалежний код","\u002Fcsharp\u002Fado-net\u002Fprovider-factory","01.csharp\u002F09.ado-net\u002F07.provider-factory",{"title":438,"path":439,"stem":440},"9.8. Асинхронний доступ до даних","\u002Fcsharp\u002Fado-net\u002Fasync-data-access","01.csharp\u002F09.ado-net\u002F08.async-data-access",{"title":442,"path":443,"stem":444},"9.9. Від'єднаний режим: DataSet, DataTable, DataRow","\u002Fcsharp\u002Fado-net\u002Fdisconnected-mode-dataset","01.csharp\u002F09.ado-net\u002F09.disconnected-mode-dataset",{"title":446,"path":447,"stem":448},"9.10. DataAdapter — міст між DataSet та базою даних","\u002Fcsharp\u002Fado-net\u002Fdata-adapter","01.csharp\u002F09.ado-net\u002F10.data-adapter",{"title":450,"path":451,"stem":452},"9.11. Data Mapper та Repository: Архітектура доступу до даних","\u002Fcsharp\u002Fado-net\u002Fdata-mapper-repository","01.csharp\u002F09.ado-net\u002F11.data-mapper-repository",{"title":454,"path":455,"stem":456},"9.12. Identity Map, Unit of Work та Specification Pattern","\u002Fcsharp\u002Fado-net\u002Fadvanced-patterns","01.csharp\u002F09.ado-net\u002F12.advanced-patterns",{"title":458,"icon":255,"path":459,"stem":460,"children":461,"page":59},"Ef Core","\u002Fcsharp\u002Fef-core","01.csharp\u002F10.ef-core",[462,466,470,474,478,482,486,490,494,498,502,506,510,514,518,522,526,532,538,542,546,550,554,558,562,566,570,574,578,582,586,590,594,598,602,606,610,614,618,622,626,630,634,638,642,646],{"title":463,"path":464,"stem":465},"Що таке ORM? Від SQL до об'єктів","\u002Fcsharp\u002Fef-core\u002Fwhat-is-orm","01.csharp\u002F10.ef-core\u002F01.what-is-orm",{"title":467,"path":468,"stem":469},"Перший проєкт — від нуля до CRUD","\u002Fcsharp\u002Fef-core\u002Ffirst-project","01.csharp\u002F10.ef-core\u002F02.first-project",{"title":471,"path":472,"stem":473},"DbContext — Серце EF Core","\u002Fcsharp\u002Fef-core\u002Fdbcontext-deep-dive","01.csharp\u002F10.ef-core\u002F03.dbcontext-deep-dive",{"title":475,"path":476,"stem":477},"Провайдери баз даних — Архітектура та Вибір СУБД","\u002Fcsharp\u002Fef-core\u002Fdatabase-providers","01.csharp\u002F10.ef-core\u002F04.database-providers",{"title":479,"path":480,"stem":481},"Конвенції EF Core — Магія без конфігурації","\u002Fcsharp\u002Fef-core\u002Fconventions","01.csharp\u002F10.ef-core\u002F05.conventions",{"title":483,"path":484,"stem":485},"Fluent API та Data Annotations — Явна конфігурація моделі","\u002Fcsharp\u002Fef-core\u002Ffluent-api-vs-annotations","01.csharp\u002F10.ef-core\u002F06.fluent-api-vs-annotations",{"title":487,"path":488,"stem":489},"Зв'язки — One-to-One та One-to-Many","\u002Fcsharp\u002Fef-core\u002Frelationships-basics","01.csharp\u002F10.ef-core\u002F07.relationships-basics",{"title":491,"path":492,"stem":493},"Зв'язки Advanced — Many-to-Many та Складні Сценарії","\u002Fcsharp\u002Fef-core\u002Frelationships-advanced","01.csharp\u002F10.ef-core\u002F08.relationships-advanced",{"title":495,"path":496,"stem":497},"Властивості — Типи, Конвертери, Компаратори (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fproperty-configuration-part1","01.csharp\u002F10.ef-core\u002F09.property-configuration-part1",{"title":499,"path":500,"stem":501},"Властивості — Value Comparers, Generators, Shadow Properties (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fproperty-configuration-part2","01.csharp\u002F10.ef-core\u002F09.property-configuration-part2",{"title":503,"path":504,"stem":505},"Складні типи — Owned Types та Complex Types (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fcomplex-types-owned-part1","01.csharp\u002F10.ef-core\u002F10.complex-types-owned-part1",{"title":507,"path":508,"stem":509},"Складні типи — Complex Types, Keyless Entities, Порівняння (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fcomplex-types-owned-part2","01.csharp\u002F10.ef-core\u002F10.complex-types-owned-part2",{"title":511,"path":512,"stem":513},"JSON Columns — Складні дані у JSON (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fjson-columns-part1","01.csharp\u002F10.ef-core\u002F11.json-columns-part1",{"title":515,"path":516,"stem":517},"JSON Columns — Value Comparers, Індекси, Провайдери (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fjson-columns-part2","01.csharp\u002F10.ef-core\u002F11.json-columns-part2",{"title":519,"path":520,"stem":521},"Успадкування — Абстрактні класи та TPH (Частина 1)","\u002Fcsharp\u002Fef-core\u002Finheritance-part1","01.csharp\u002F10.ef-core\u002F12.inheritance-part1",{"title":523,"path":524,"stem":525},"Успадкування — TPT, TPC та Порівняння Стратегій (Частина 2)","\u002Fcsharp\u002Fef-core\u002Finheritance-part2","01.csharp\u002F10.ef-core\u002F12.inheritance-part2",{"title":527,"path":528,"stem":529,"children":530},"Індекси, Обмеження та Схема (Частина 1)","\u002Fcsharp\u002Fef-core\u002Findexes-constraints-part1","01.csharp\u002F10.ef-core\u002F13.indexes-constraints-part1",[531],{"title":527,"path":528,"stem":529},{"title":533,"path":534,"stem":535,"children":536},"Індекси, Обмеження та Схема (Частина 2)","\u002Fcsharp\u002Fef-core\u002Findexes-constraints-part2","01.csharp\u002F10.ef-core\u002F13.indexes-constraints-part2",[537],{"title":533,"path":534,"stem":535},{"title":539,"path":540,"stem":541},"Seed Data — Початкові Дані (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fseeding-part1","01.csharp\u002F10.ef-core\u002F14.seeding-part1",{"title":543,"path":544,"stem":545},"Seed Data — SQL-скрипти, Bogus та Стратегії (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fseeding-part2","01.csharp\u002F10.ef-core\u002F14.seeding-part2",{"title":547,"path":548,"stem":549},"Global Query Filters — Глобальні Фільтри (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fglobal-query-filters-part1","01.csharp\u002F10.ef-core\u002F15.global-query-filters-part1",{"title":551,"path":552,"stem":553},"Global Query Filters — Підводні камені та Інтеграція (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fglobal-query-filters-part2","01.csharp\u002F10.ef-core\u002F15.global-query-filters-part2",{"title":555,"path":556,"stem":557},"LINQ-запити в EF Core (Частина 1)","\u002Fcsharp\u002Fef-core\u002Flinq-queries-part1","01.csharp\u002F10.ef-core\u002F16.linq-queries-part1",{"title":559,"path":560,"stem":561},"LINQ-запити в EF Core (Частина 2)","\u002Fcsharp\u002Fef-core\u002Flinq-queries-part2","01.csharp\u002F10.ef-core\u002F16.linq-queries-part2",{"title":563,"path":564,"stem":565},"Завантаження Пов'язаних Даних (Частина 1)","\u002Fcsharp\u002Fef-core\u002Floading-related-data-part1","01.csharp\u002F10.ef-core\u002F17.loading-related-data-part1",{"title":567,"path":568,"stem":569},"Завантаження Пов'язаних Даних (Частина 2)","\u002Fcsharp\u002Fef-core\u002Floading-related-data-part2","01.csharp\u002F10.ef-core\u002F17.loading-related-data-part2",{"title":571,"path":572,"stem":573},"Raw SQL, Views та Stored Procedures (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fraw-sql-part1","01.csharp\u002F10.ef-core\u002F18.raw-sql-part1",{"title":575,"path":576,"stem":577},"Raw SQL — Stored Procedures, DbFunction та Bulk Operations (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fraw-sql-part2","01.csharp\u002F10.ef-core\u002F18.raw-sql-part2",{"title":579,"path":580,"stem":581},"Продвинуті Запити — Compiled Queries, Bulk та Оптимізація (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fadvanced-queries-part1","01.csharp\u002F10.ef-core\u002F19.advanced-queries-part1",{"title":583,"path":584,"stem":585},"Продвинуті Запити — Query Tags, Bulk та Interceptors (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fadvanced-queries-part2","01.csharp\u002F10.ef-core\u002F19.advanced-queries-part2",{"title":587,"path":588,"stem":589},"Change Tracker — Відстеження Змін (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fchange-tracking-part1","01.csharp\u002F10.ef-core\u002F20.change-tracking-part1",{"title":591,"path":592,"stem":593},"Change Tracker — Графи Об'єктів та Disconnected (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fchange-tracking-part2","01.csharp\u002F10.ef-core\u002F20.change-tracking-part2",{"title":595,"path":596,"stem":597},"Збереження Даних та Транзакції (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fsaving-data-part1","01.csharp\u002F10.ef-core\u002F21.saving-data-part1",{"title":599,"path":600,"stem":601},"Збереження Даних — Concurrency та Outbox (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fsaving-data-part2","01.csharp\u002F10.ef-core\u002F21.saving-data-part2",{"title":603,"path":604,"stem":605},"Конкурентність та Блокування (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fconcurrency-part1","01.csharp\u002F10.ef-core\u002F22.concurrency-part1",{"title":607,"path":608,"stem":609},"Конкурентність — Дедлоки та Queue Processing (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fconcurrency-part2","01.csharp\u002F10.ef-core\u002F22.concurrency-part2",{"title":611,"path":612,"stem":613},"Міграції в EF Core — Основи (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fmigrations-basics-part1","01.csharp\u002F10.ef-core\u002F23.migrations-basics-part1",{"title":615,"path":616,"stem":617},"Міграції в EF Core — Основи (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fmigrations-basics-part2","01.csharp\u002F10.ef-core\u002F23.migrations-basics-part2",{"title":619,"path":620,"stem":621},"Міграції — Просунуті Сценарії (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fmigrations-advanced-part1","01.csharp\u002F10.ef-core\u002F24.migrations-advanced-part1",{"title":623,"path":624,"stem":625},"Міграції — Просунуті Сценарії (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fmigrations-advanced-part2","01.csharp\u002F10.ef-core\u002F24.migrations-advanced-part2",{"title":627,"path":628,"stem":629},"Управління Схемою та Database-First (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fschema-management-part1","01.csharp\u002F10.ef-core\u002F25.schema-management-part1",{"title":631,"path":632,"stem":633},"Управління Схемою та Database-First (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fschema-management-part2","01.csharp\u002F10.ef-core\u002F25.schema-management-part2",{"title":635,"path":636,"stem":637},"Продуктивність EF Core — Основи (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fperformance-fundamentals-part1","01.csharp\u002F10.ef-core\u002F26.performance-fundamentals-part1",{"title":639,"path":640,"stem":641},"Interceptors в EF Core (Частина 1)","\u002Fcsharp\u002Fef-core\u002Finterceptors-part1","01.csharp\u002F10.ef-core\u002F29.interceptors-part1",{"title":643,"path":644,"stem":645},"Interceptors в EF Core — Connection, Transaction та Materialization (Частина 2)","\u002Fcsharp\u002Fef-core\u002Finterceptors-part2","01.csharp\u002F10.ef-core\u002F29.interceptors-part2",{"title":647,"path":648,"stem":649},"План вивчення Entity Framework Core — Повний курс","\u002Fcsharp\u002Fef-core\u002Fimplementation_plan","01.csharp\u002F10.ef-core\u002Fimplementation_plan",{"title":651,"icon":652,"path":653,"stem":654,"children":655,"page":59},"ASP.NET","i-devicon-dotnetcore","\u002Fcsharp\u002Faspnet","01.csharp\u002F11.aspnet",[656,730,791,869,927,941,967,1057,1111,1182,1212,1289,1346],{"title":657,"icon":658,"path":659,"stem":660,"children":661,"page":59},"Minimal API","i-lucide-network","\u002Fcsharp\u002Faspnet\u002Fminimal-api","01.csharp\u002F11.aspnet\u002F01.minimal-api",[662,666,670,674,678,682,686,690,694,698,702,706,710,714,718,722,726],{"title":663,"path":664,"stem":665},"Вступ до ASP.NET та еволюція фреймворку","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fintroduction","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F01.introduction",{"title":667,"path":668,"stem":669},"Перший додаток на ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Ffirst-application","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F02.first-application",{"title":671,"path":672,"stem":673},"WebApplication, Builder та Dependency Injection","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fwebapplication-builder","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F03.webapplication-builder",{"title":675,"path":676,"stem":677},"Конвеєр запитів та Middleware","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Frequest-pipeline-middleware","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F04.request-pipeline-middleware",{"title":679,"path":680,"stem":681},"Маршрутизація в ASP.NET Core: Основи","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Frouting-basics","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F05.routing-basics",{"title":683,"path":684,"stem":685},"Маршрутизація в ASP.NET Core: Розширені можливості","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Frouting-advanced","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F06.routing-advanced",{"title":687,"path":688,"stem":689},"Статичні файли в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fstatic-files","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F07.static-files",{"title":691,"path":692,"stem":693},"Статичні Активи: MapStaticAssets (ASP.NET Core 9.0)","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fstatic-assets","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F08.static-assets",{"title":695,"path":696,"stem":697},"Конфігурація в ASP.NET Core: Основи","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fconfiguration-fundamentals","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F09.configuration-fundamentals",{"title":699,"path":700,"stem":701},"Конфігурація: Паттерн Options","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fconfiguration-options","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F10.configuration-options",{"title":703,"path":704,"stem":705},"Логування в ASP.NET Core: Основи","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Flogging-basics","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F11.logging-basics",{"title":707,"path":708,"stem":709},"Логування: Serilog та Middleware","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Flogging-advanced","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F12.logging-advanced",{"title":711,"path":712,"stem":713},"Управління станом: HttpContext.Items та Cookies","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fstate-management","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F13.state-management",{"title":715,"path":716,"stem":717},"Стан сесії: Sessions","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fsession-state","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F14.session-state",{"title":719,"path":720,"stem":721},"Структура проєкту: від хаосу до архітектури","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fproject-structure","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F15.project-structure",{"title":723,"path":724,"stem":725},"Scalar у Minimal API: повний проєкт і Fluent OpenAPI","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fscalar-openapi-fluent","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F16.scalar-openapi-fluent",{"title":727,"path":728,"stem":729},"Swagger \u002F Swashbuckle у Minimal API: окремий класичний шлях","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fswagger-swashbuckle","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F17.swagger-swashbuckle",{"title":731,"icon":658,"path":732,"stem":733,"children":734,"page":59},"API","\u002Fcsharp\u002Faspnet\u002Fapi","01.csharp\u002F11.aspnet\u002F02.api",[735,739,743,747,751,755,759,763,767,771,775,779,783,787],{"title":736,"path":737,"stem":738},"Що таке API. Клієнт-серверна архітектура","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fwhat-is-api","01.csharp\u002F11.aspnet\u002F02.api\u002F01.what-is-api",{"title":740,"path":741,"stem":742},"Формати даних: JSON, XML, TOML та бінарні формати","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fdata-formats","01.csharp\u002F11.aspnet\u002F02.api\u002F02.data-formats",{"title":744,"path":745,"stem":746},"Парадигми API та концепція REST","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fapi-paradigms-rest","01.csharp\u002F11.aspnet\u002F02.api\u002F03.api-paradigms-rest",{"title":748,"path":749,"stem":750},"HTTP-методи, статус-коди та заголовки","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fhttp-methods-status-codes","01.csharp\u002F11.aspnet\u002F02.api\u002F04.http-methods-status-codes",{"title":752,"path":753,"stem":754},"Організація HTTP API за принципами REST","\u002Fcsharp\u002Faspnet\u002Fapi\u002Frest-organizing","01.csharp\u002F11.aspnet\u002F02.api\u002F05.rest-organizing",{"title":756,"path":757,"stem":758},"Номенклатура URL та CRUD-операції","\u002Fcsharp\u002Faspnet\u002Fapi\u002Furl-nomenclature-crud","01.csharp\u002F11.aspnet\u002F02.api\u002F06.url-nomenclature-crud",{"title":760,"path":761,"stem":762},"Правила дизайну: іменування та стандарти","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fapi-design-naming","01.csharp\u002F11.aspnet\u002F02.api\u002F07.api-design-naming",{"title":764,"path":765,"stem":766},"Валідація, ліміти та обробка помилок","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fapi-design-validation","01.csharp\u002F11.aspnet\u002F02.api\u002F08.api-design-validation",{"title":768,"path":769,"stem":770},"Обробка помилок у Minimal API","\u002Fcsharp\u002Faspnet\u002Fapi\u002Ferror-handling-http","01.csharp\u002F11.aspnet\u002F02.api\u002F09.error-handling-http",{"title":772,"path":773,"stem":774},"Ідемпотентність та синхронізація стану","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fidempotency-sync","01.csharp\u002F11.aspnet\u002F02.api\u002F10.idempotency-sync",{"title":776,"path":777,"stem":778},"Пагінація та організація списків","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fpagination-lists","01.csharp\u002F11.aspnet\u002F02.api\u002F11.pagination-lists",{"title":780,"path":781,"stem":782},"Безпека API, кешування та інтернаціоналізація","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fsecurity-auth","01.csharp\u002F11.aspnet\u002F02.api\u002F12.security-auth",{"title":784,"path":785,"stem":786},"Процес проєктування API та документування","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fapi-design-process","01.csharp\u002F11.aspnet\u002F02.api\u002F13.api-design-process",{"title":788,"path":789,"stem":790},"OpenAPI: контракт, специфікація та документація API","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fopenapi","01.csharp\u002F11.aspnet\u002F02.api\u002F14.openapi",{"title":792,"icon":793,"path":794,"stem":795,"children":796,"page":59},"Auth","i-lucide-shield-check","\u002Fcsharp\u002Faspnet\u002Fauth","01.csharp\u002F11.aspnet\u002F03.auth",[797,801,805,809,813,817,821,825,829,833,837,841,845,849,853,857,861,865],{"title":798,"path":799,"stem":800},"Основи аутентифікації та авторизації","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fauth-fundamentals","01.csharp\u002F11.aspnet\u002F03.auth\u002F01.auth-fundamentals",{"title":802,"path":803,"stem":804},"JWT-аутентифікація","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fjwt-authentication","01.csharp\u002F11.aspnet\u002F03.auth\u002F02.jwt-authentication",{"title":806,"path":807,"stem":808},"Авторизація: ролі, політики та resource-based доступ","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fauthorization-policies","01.csharp\u002F11.aspnet\u002F03.auth\u002F03.authorization-policies",{"title":810,"path":811,"stem":812},"Cookie-аутентифікація та ASP.NET Core Identity","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fcookie-auth-identity","01.csharp\u002F11.aspnet\u002F03.auth\u002F04.cookie-auth-identity",{"title":814,"path":815,"stem":816},"JWT + Refresh Tokens (HttpOnly Cookie)","\u002Fcsharp\u002Faspnet\u002Fauth\u002F04b.identity-auth-jwt","01.csharp\u002F11.aspnet\u002F03.auth\u002F04b.identity-auth-jwt",{"title":818,"path":819,"stem":820},"Identity: Підтвердження Email та Скидання Пароля","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fidentity-email-confirmation","01.csharp\u002F11.aspnet\u002F03.auth\u002F05.identity-email-confirmation",{"title":822,"path":823,"stem":824},"Identity: Двофакторна Аутентифікація (2FA)","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fidentity-two-factor","01.csharp\u002F11.aspnet\u002F03.auth\u002F06.identity-two-factor",{"title":826,"path":827,"stem":828},"Identity: Внутрішня Архітектура та Кастомізація","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fidentity-internals","01.csharp\u002F11.aspnet\u002F03.auth\u002F07.identity-internals",{"title":830,"path":831,"stem":832},"OAuth 2.0 та зовнішні провайдери","\u002Fcsharp\u002Faspnet\u002Fauth\u002Foauth-external-providers","01.csharp\u002F11.aspnet\u002F03.auth\u002F08.oauth-external-providers",{"title":834,"path":835,"stem":836},"Безпека на практиці: CORS, HTTPS та захист від атак","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fsecurity-hardening","01.csharp\u002F11.aspnet\u002F03.auth\u002F09.security-hardening",{"title":838,"path":839,"stem":840},"Теорія OAuth 2.0: Поняття, Аналогії та Флоу","\u002Fcsharp\u002Faspnet\u002Fauth\u002Foauth-theory","01.csharp\u002F11.aspnet\u002F03.auth\u002F10.oauth-theory",{"title":842,"path":843,"stem":844},"OIDC, OAuth 2.0 та Keycloak в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Foidc-keycloak","01.csharp\u002F11.aspnet\u002F03.auth\u002F10.oidc-keycloak",{"title":846,"path":847,"stem":848},"API Keys аутентифікація в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fapi-keys","01.csharp\u002F11.aspnet\u002F03.auth\u002F11.api-keys",{"title":850,"path":851,"stem":852},"Rate Limiting та Throttling в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Frate-limiting","01.csharp\u002F11.aspnet\u002F03.auth\u002F12.rate-limiting",{"title":854,"path":855,"stem":856},"Refresh Token Rotation в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Frefresh-token-rotation","01.csharp\u002F11.aspnet\u002F03.auth\u002F13.refresh-token-rotation",{"title":858,"path":859,"stem":860},"Certificate Authentication та mTLS в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fcertificate-auth","01.csharp\u002F11.aspnet\u002F03.auth\u002F14.certificate-auth",{"title":862,"path":863,"stem":864},"RBAC, ABAC та ReBAC в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Frbac-abac-rebac","01.csharp\u002F11.aspnet\u002F03.auth\u002F15.rbac-abac-rebac",{"title":866,"path":867,"stem":868},"Multi-tenancy та ізоляція даних в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fmulti-tenancy","01.csharp\u002F11.aspnet\u002F03.auth\u002F16.multi-tenancy",{"title":870,"icon":871,"path":872,"stem":873,"children":874,"page":59},"Нотифікації","i-lucide-bell","\u002Fcsharp\u002Faspnet\u002Fnotifications","01.csharp\u002F11.aspnet\u002F04.notifications",[875,879,883,887,891,895,899,903,907,911,915,919,923],{"title":876,"path":877,"stem":878},"In-App нотифікації через базу даних","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fin-app-database-notifications","01.csharp\u002F11.aspnet\u002F04.notifications\u002F01.in-app-database-notifications",{"title":880,"path":881,"stem":882},"Polling: Регулярний запит оновлень","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fpolling","01.csharp\u002F11.aspnet\u002F04.notifications\u002F02.polling",{"title":884,"path":885,"stem":886},"Server-Sent Events: Однострімовий push від сервера","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fserver-sent-events","01.csharp\u002F11.aspnet\u002F04.notifications\u002F03.server-sent-events",{"title":888,"path":889,"stem":890},"WebSockets: Двостороннє з'єднання в реальному часі","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fwebsockets","01.csharp\u002F11.aspnet\u002F04.notifications\u002F04.websockets",{"title":892,"path":893,"stem":894},"SignalR: Абстракція над транспортами реального часу","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fsignalr","01.csharp\u002F11.aspnet\u002F04.notifications\u002F05.signalr",{"title":896,"path":897,"stem":898},"Background Services: Фонові задачі в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fbackground-services","01.csharp\u002F11.aspnet\u002F04.notifications\u002F06.background-services",{"title":900,"path":901,"stem":902},"Web Push нотифікації","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fweb-push","01.csharp\u002F11.aspnet\u002F04.notifications\u002F07.web-push",{"title":904,"path":905,"stem":906},"Email нотифікації","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Femail-notifications","01.csharp\u002F11.aspnet\u002F04.notifications\u002F08.email-notifications",{"title":908,"path":909,"stem":910},"Порівняння підходів: Як вибрати правильну технологію нотифікацій","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fchoosing-the-right-approach","01.csharp\u002F11.aspnet\u002F04.notifications\u002F09.choosing-the-right-approach",{"title":912,"path":913,"stem":914},"Hangfire: Надійне планування фонових задач","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fhangfire","01.csharp\u002F11.aspnet\u002F04.notifications\u002F10.hangfire",{"title":916,"path":917,"stem":918},"Практика: Конвертація зображень у WebP через Hangfire","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fhangfire-image-webp","01.csharp\u002F11.aspnet\u002F04.notifications\u002F11.hangfire-image-webp",{"title":920,"path":921,"stem":922},"Практика: Підготовка відео до HLS-стрімінгу через Hangfire","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fhangfire-video-hls","01.csharp\u002F11.aspnet\u002F04.notifications\u002F12.hangfire-video-hls",{"title":924,"path":925,"stem":926},"Telegram-нотифікації: від одного повідомлення до масових розсилок і мульти-канального підходу","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Ftelegram-notifications","01.csharp\u002F11.aspnet\u002F04.notifications\u002F13.telegram-notifications",{"title":928,"icon":929,"path":930,"stem":931,"children":932,"page":59},"Інтернаціоналізація","i-lucide-languages","\u002Fcsharp\u002Faspnet\u002Fi18n","01.csharp\u002F11.aspnet\u002F05.i18n",[933,937],{"title":934,"path":935,"stem":936},"Інтернаціоналізація (i18n) у Minimal API: від A до Я","\u002Fcsharp\u002Faspnet\u002Fi18n\u002Finternationalization","01.csharp\u002F11.aspnet\u002F05.i18n\u002F01.internationalization",{"title":938,"path":939,"stem":940},"Humanizer: людиномовні рядки у .NET","\u002Fcsharp\u002Faspnet\u002Fi18n\u002Fhumanizer","01.csharp\u002F11.aspnet\u002F05.i18n\u002F02.humanizer",{"title":942,"icon":943,"path":944,"stem":945,"children":946,"page":59},"Кешування","i-lucide-layers","\u002Fcsharp\u002Faspnet\u002Fcaching","01.csharp\u002F11.aspnet\u002F06.caching",[947,951,955,959,963],{"title":948,"path":949,"stem":950},"Огляд кешування: чотири рівні і коли що обирати","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Fcaching","01.csharp\u002F11.aspnet\u002F06.caching\u002F01.caching",{"title":952,"path":953,"stem":954},"IMemoryCache: кеш в оперативній пам'яті","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Fmemory-cache","01.csharp\u002F11.aspnet\u002F06.caching\u002F02.memory-cache",{"title":956,"path":957,"stem":958},"IDistributedCache і Redis: розподілений кеш","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Fdistributed-cache","01.csharp\u002F11.aspnet\u002F06.caching\u002F03.distributed-cache",{"title":960,"path":961,"stem":962},"Response Cache: HTTP-кешування через Cache-Control","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Fresponse-cache","01.csharp\u002F11.aspnet\u002F06.caching\u002F04.response-cache",{"title":964,"path":965,"stem":966},"Output Cache: серверний кеш HTTP-відповідей (.NET 7+)","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Foutput-cache","01.csharp\u002F11.aspnet\u002F06.caching\u002F05.output-cache",{"title":968,"icon":969,"path":970,"stem":971,"children":972,"page":59},"Тестування","i-lucide-test-tube","\u002Fcsharp\u002Faspnet\u002Ftesting","01.csharp\u002F11.aspnet\u002F07.testing",[973,977,981,985,989,993,997,1001,1005,1009,1013,1017,1021,1025,1029,1033,1037,1041,1045,1049,1053],{"title":974,"path":975,"stem":976},"Що таке тестування? Від інтуїції до науки","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fwhat-is-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F01.what-is-testing",{"title":978,"path":979,"stem":980},"Піраміда тестування — Стратегія, а не Догма","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftesting-pyramid","01.csharp\u002F11.aspnet\u002F07.testing\u002F02.testing-pyramid",{"title":982,"path":983,"stem":984},"Дві Школи Тестування — Лондон проти Детройту","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftesting-schools","01.csharp\u002F11.aspnet\u002F07.testing\u002F03.testing-schools",{"title":986,"path":987,"stem":988},"TDD та BDD — Тести як Дизайн-інструмент","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftdd-and-bdd","01.csharp\u002F11.aspnet\u002F07.testing\u002F04.tdd-and-bdd",{"title":990,"path":991,"stem":992},"Що саме тестувати — Техніки аналізу та Циклomatична складність","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fwhat-to-test","01.csharp\u002F11.aspnet\u002F07.testing\u002F05.what-to-test",{"title":994,"path":995,"stem":996},"Тестові Фреймворки — Навіщо вони і що всередині","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftest-frameworks","01.csharp\u002F11.aspnet\u002F07.testing\u002F06.test-frameworks",{"title":998,"path":999,"stem":1000},"xUnit — Факти, Теорії та Lifecycle тестів","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fxunit-basics","01.csharp\u002F11.aspnet\u002F07.testing\u002F07.xunit-basics",{"title":1002,"path":1003,"stem":1004},"xUnit Advanced — Fixtures, Кастомізація та Розширення","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fxunit-advanced","01.csharp\u002F11.aspnet\u002F07.testing\u002F08.xunit-advanced",{"title":1006,"path":1007,"stem":1008},"Moq — Глибоке занурення в мокування","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fmocking-with-moq","01.csharp\u002F11.aspnet\u002F07.testing\u002F09.mocking-with-moq",{"title":1010,"path":1011,"stem":1012},"Тестування Баз Даних — EF Core, SQLite та Testcontainers","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fdatabase-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F10.database-testing",{"title":1014,"path":1015,"stem":1016},"Integration Testing — Частина 1 [Теорія та WebApplicationFactory]","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fintegration-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F11.integration-testing",{"title":1018,"path":1019,"stem":1020},"Інтеграційне тестування — Практика","\u002Fcsharp\u002Faspnet\u002Ftesting\u002F11a.integration-testing-practice","01.csharp\u002F11.aspnet\u002F07.testing\u002F11a.integration-testing-practice",{"title":1022,"path":1023,"stem":1024},"Integration Testing — Частина 2 [Просунуті Сценарії та Testcontainers]","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fintegration-testing-advanced","01.csharp\u002F11.aspnet\u002F07.testing\u002F12.integration-testing-advanced",{"title":1026,"path":1027,"stem":1028},"Професійний Postman: Колекції, Змінні та GitHub Інтеграція","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fpostman-professional","01.csharp\u002F11.aspnet\u002F07.testing\u002F13.postman-professional",{"title":1030,"path":1031,"stem":1032},"HttpClient у Тестах Частина 1: Архітектура та MockHttpMessageHandler","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fhttpclient-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F14.httpclient-testing",{"title":1034,"path":1035,"stem":1036},"HttpClient у Тестах Частина 2: WireMock.Net та Resilience","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fwiremock-net","01.csharp\u002F11.aspnet\u002F07.testing\u002F15.wiremock-net",{"title":1038,"path":1039,"stem":1040},"Патерни та Анти-патерни Тестування: Test Smells","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftesting-patterns","01.csharp\u002F11.aspnet\u002F07.testing\u002F16.testing-patterns",{"title":1042,"path":1043,"stem":1044},"Просунуті інструменти: Time, Snapshots та Властивості","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fadvanced-testing-tools","01.csharp\u002F11.aspnet\u002F07.testing\u002F17.advanced-testing-tools",{"title":1046,"path":1047,"stem":1048},"Тестування Архітектури з NetArchTest","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Farchitecture-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F18.architecture-testing",{"title":1050,"path":1051,"stem":1052},"Тестування Продуктивності: BenchmarkDotNet, NBomber та k6","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fperformance-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F19.performance-testing",{"title":1054,"path":1055,"stem":1056},"Залишок плану для курсу \"Тестування ASP.NET Minimal API\"","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fremaining_plan","01.csharp\u002F11.aspnet\u002F07.testing\u002Fremaining_plan",{"title":1058,"icon":1059,"path":1060,"stem":1061,"children":1062,"page":59},"Платежі","i-lucide-credit-card","\u002Fcsharp\u002Faspnet\u002Fpayments","01.csharp\u002F11.aspnet\u002F08.payments",[1063,1067,1071,1075,1079,1083,1087,1091,1095,1099,1103,1107],{"title":1064,"path":1065,"stem":1066},"Основи платіжної інфраструктури","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fpayment-fundamentals","01.csharp\u002F11.aspnet\u002F08.payments\u002F01.payment-fundamentals",{"title":1068,"path":1069,"stem":1070},"Методи оплати в Україні","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fpayment-methods-ukraine","01.csharp\u002F11.aspnet\u002F08.payments\u002F02.payment-methods-ukraine",{"title":1072,"path":1073,"stem":1074},"PCI DSS та безпека платежів","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fpci-dss-security","01.csharp\u002F11.aspnet\u002F08.payments\u002F03.pci-dss-security",{"title":1076,"path":1077,"stem":1078},"Архітектура платіжної підсистеми","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fpayment-architecture","01.csharp\u002F11.aspnet\u002F08.payments\u002F04.payment-architecture",{"title":1080,"path":1081,"stem":1082},"Інтеграція LiqPay (ПриватБанк)","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fliqpay-integration","01.csharp\u002F11.aspnet\u002F08.payments\u002F05.liqpay-integration",{"title":1084,"path":1085,"stem":1086},"Інтеграція Monobank Acquiring API","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fmonobank-acquiring","01.csharp\u002F11.aspnet\u002F08.payments\u002F06.monobank-acquiring",{"title":1088,"path":1089,"stem":1090},"Інтеграція Stripe","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fstripe-integration","01.csharp\u002F11.aspnet\u002F08.payments\u002F07.stripe-integration",{"title":1092,"path":1093,"stem":1094},"Webhooks — глибоке занурення","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fwebhooks-deep-dive","01.csharp\u002F11.aspnet\u002F08.payments\u002F08.webhooks-deep-dive",{"title":1096,"path":1097,"stem":1098},"Підписки та рекурентні платежі","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fsubscriptions-recurring","01.csharp\u002F11.aspnet\u002F08.payments\u002F09.subscriptions-recurring",{"title":1100,"path":1101,"stem":1102},"Повернення коштів та диспути","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Frefunds-disputes","01.csharp\u002F11.aspnet\u002F08.payments\u002F10.refunds-disputes",{"title":1104,"path":1105,"stem":1106},"Тестування платіжних інтеграцій","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Ftesting-payments","01.csharp\u002F11.aspnet\u002F08.payments\u002F11.testing-payments",{"title":1108,"path":1109,"stem":1110},"Чекліст виходу в Production","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fproduction-checklist","01.csharp\u002F11.aspnet\u002F08.payments\u002F12.production-checklist",{"title":1112,"icon":1113,"items":1114,"path":1127,"stem":1128,"children":1129,"page":59},"Популярні бібліотеки","lucide:box",[1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126],"01.fluent-validation","02.mapster","03.erroror-result-pattern","04.serilog","05.mediatr","06.polly","07.health-checks","08.feature-management","09.fluent-email","10.quest-pdf","11.bogus","12.humanizer-guard","\u002Fcsharp\u002Faspnet\u002Flibraries","01.csharp\u002F11.aspnet\u002F09.libraries",[1130,1134,1138,1142,1146,1150,1154,1158,1162,1166,1170,1174,1178],{"title":1131,"path":1132,"stem":1133},"Валідація з FluentValidation в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Ffluent-validation","01.csharp\u002F11.aspnet\u002F09.libraries\u002F01.fluent-validation",{"title":1135,"path":1136,"stem":1137},"Маппінг об","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fmapster","01.csharp\u002F11.aspnet\u002F09.libraries\u002F02.mapster",{"title":1139,"path":1140,"stem":1141},"Обробка помилок з ErrorOr та Result Pattern в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Ferroror-result-pattern","01.csharp\u002F11.aspnet\u002F09.libraries\u002F03.erroror-result-pattern",{"title":1143,"path":1144,"stem":1145},"Структуроване логування з Serilog в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fserilog","01.csharp\u002F11.aspnet\u002F09.libraries\u002F04.serilog",{"title":1147,"path":1148,"stem":1149},"CQRS та Mediator з MediatR в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fmediatr","01.csharp\u002F11.aspnet\u002F09.libraries\u002F05.mediatr",{"title":1151,"path":1152,"stem":1153},"Відмовостійкість з Polly в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fpolly","01.csharp\u002F11.aspnet\u002F09.libraries\u002F06.polly",{"title":1155,"path":1156,"stem":1157},"Health Checks в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fhealth-checks","01.csharp\u002F11.aspnet\u002F09.libraries\u002F07.health-checks",{"title":1159,"path":1160,"stem":1161},"Feature Management та Feature Flags в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Ffeature-management","01.csharp\u002F11.aspnet\u002F09.libraries\u002F08.feature-management",{"title":1163,"path":1164,"stem":1165},"Відправка Email з FluentEmail в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Ffluent-email","01.csharp\u002F11.aspnet\u002F09.libraries\u002F09.fluent-email",{"title":1167,"path":1168,"stem":1169},"Генерація PDF з QuestPDF в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fquest-pdf","01.csharp\u002F11.aspnet\u002F09.libraries\u002F10.quest-pdf",{"title":1171,"path":1172,"stem":1173},"Генерація тестових даних з Bogus в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fbogus","01.csharp\u002F11.aspnet\u002F09.libraries\u002F11.bogus",{"title":1175,"path":1176,"stem":1177},"Humanizer та Guard Clauses в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fhumanizer-guard","01.csharp\u002F11.aspnet\u002F09.libraries\u002F12.humanizer-guard",{"title":1179,"path":1180,"stem":1181},"План модуля 10.libraries — Популярні бібліотеки ASP.NET","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fplan","01.csharp\u002F11.aspnet\u002F09.libraries\u002Fplan",{"title":1183,"icon":1184,"path":1185,"stem":1186,"children":1187,"page":59},"Razor Pages","i-lucide-layout-template","\u002Fcsharp\u002Faspnet\u002Frazor-pages","01.csharp\u002F11.aspnet\u002F10.razor-pages",[1188,1192,1196,1200,1204,1208],{"title":1189,"path":1190,"stem":1191},"Від Minimal API до Razor Pages: концептуальний перехід","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Ffrom-minimal-api","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F01.from-minimal-api",{"title":1193,"path":1194,"stem":1195},"PageModel: логіка сторінки Razor Pages","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Fpage-model","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F02.page-model",{"title":1197,"path":1198,"stem":1199},"Razor синтаксис: шаблонізатор у .cshtml","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Frazor-syntax","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F03.razor-syntax",{"title":1201,"path":1202,"stem":1203},"Tag Helpers: типізований HTML","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Ftag-helpers","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F04.tag-helpers",{"title":1205,"path":1206,"stem":1207},"Форми і валідація: повний цикл обробки даних","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Fforms-validation","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F05.forms-validation",{"title":1209,"path":1210,"stem":1211},"Практичний проєкт: TaskManager на Razor Pages","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Fproject-task-manager","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F06.project-task-manager",{"title":1213,"path":1214,"stem":1215,"children":1216,"page":59},"ASP.NET Core MVC","\u002Fcsharp\u002Faspnet\u002Fmvc","01.csharp\u002F11.aspnet\u002F11.mvc",[1217,1221,1225,1229,1233,1237,1241,1245,1249,1253,1257,1261,1265,1269,1273,1277,1281,1285],{"title":1218,"path":1219,"stem":1220},"Патерн MVC: архітектура, що змінила веб","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fmvc-pattern","01.csharp\u002F11.aspnet\u002F11.mvc\u002F01.mvc-pattern",{"title":1222,"path":1223,"stem":1224},"Від Razor Pages до MVC: концептуальний перехід","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Ffrom-razor-pages","01.csharp\u002F11.aspnet\u002F11.mvc\u002F02.from-razor-pages",{"title":1226,"path":1227,"stem":1228},"Controllers та Actions: серце MVC","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fcontrollers-actions","01.csharp\u002F11.aspnet\u002F11.mvc\u002F03.controllers-actions",{"title":1230,"path":1231,"stem":1232},"Маршрутизація в MVC: Convention vs Attribute Routing","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Frouting-mvc","01.csharp\u002F11.aspnet\u002F11.mvc\u002F04.routing-mvc",{"title":1234,"path":1235,"stem":1236},"Model Binding: від HTTP до C#","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fmodel-binding","01.csharp\u002F11.aspnet\u002F11.mvc\u002F05.model-binding",{"title":1238,"path":1239,"stem":1240},"Views, ViewData, ViewBag, TempData і ViewModel","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fviews-viewdata-tempdata","01.csharp\u002F11.aspnet\u002F11.mvc\u002F06.views-viewdata-tempdata",{"title":1242,"path":1243,"stem":1244},"Filters: аспектно-орієнтоване програмування в MVC","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Ffilters","01.csharp\u002F11.aspnet\u002F11.mvc\u002F07.filters",{"title":1246,"path":1247,"stem":1248},"Areas: структурування великих застосунків","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fareas","01.csharp\u002F11.aspnet\u002F11.mvc\u002F08.areas",{"title":1250,"path":1251,"stem":1252},"View Components: повторювані незалежні блоки UI","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fview-components","01.csharp\u002F11.aspnet\u002F11.mvc\u002F09.view-components",{"title":1254,"path":1255,"stem":1256},"Display та Editor Templates","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fdisplay-editor-templates","01.csharp\u002F11.aspnet\u002F11.mvc\u002F10.display-editor-templates",{"title":1258,"path":1259,"stem":1260},"Валідація: IValidatableObject та FluentValidation","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fvalidation-advanced","01.csharp\u002F11.aspnet\u002F11.mvc\u002F11.validation-advanced",{"title":1262,"path":1263,"stem":1264},"HTMX: інтерактивність через HTML-атрибути","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fhtmx","01.csharp\u002F11.aspnet\u002F11.mvc\u002F12.htmx",{"title":1266,"path":1267,"stem":1268},"HTMX у ASP.NET Core MVC: серверна інтеграція","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fajax-htmx-mvc","01.csharp\u002F11.aspnet\u002F11.mvc\u002F13.ajax-htmx-mvc",{"title":1270,"path":1271,"stem":1272},"Практичний проєкт: Каталог товарів з HTMX","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fhtmx-project","01.csharp\u002F11.aspnet\u002F11.mvc\u002F14.htmx-project",{"title":1274,"path":1275,"stem":1276},"Завантаження та обробка файлів","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Ffile-upload","01.csharp\u002F11.aspnet\u002F11.mvc\u002F15.file-upload",{"title":1278,"path":1279,"stem":1280},"Глобалізація та Локалізація MVC","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fglobalization-localization","01.csharp\u002F11.aspnet\u002F11.mvc\u002F16.globalization-localization",{"title":1282,"path":1283,"stem":1284},"Підсумковий проєкт: Блог-платформа","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fmvc-project","01.csharp\u002F11.aspnet\u002F11.mvc\u002F17.mvc-project",{"title":1286,"path":1287,"stem":1288},"План курсу: ASP.NET Core MVC","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fplan","01.csharp\u002F11.aspnet\u002F11.mvc\u002Fplan",{"title":1290,"path":1291,"stem":1292,"children":1293,"page":59},"Web Api","\u002Fcsharp\u002Faspnet\u002Fweb-api","01.csharp\u002F11.aspnet\u002F12.web-api",[1294,1298,1302,1306,1310,1314,1318,1322,1326,1330,1334,1338,1342],{"title":1295,"path":1296,"stem":1297},"Від Minimal API до Controller-based API","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Ffrom-minimal-api-to-controllers","01.csharp\u002F11.aspnet\u002F12.web-api\u002F01.from-minimal-api-to-controllers",{"title":1299,"path":1300,"stem":1301},"ControllerBase, ActionResult\u003CT> та Response Types","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fcontroller-base-actionresult","01.csharp\u002F11.aspnet\u002F12.web-api\u002F02.controller-base-actionresult",{"title":1303,"path":1304,"stem":1305},"Content Negotiation - JSON, XML та власні форматери","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fcontent-negotiation","01.csharp\u002F11.aspnet\u002F12.web-api\u002F03.content-negotiation",{"title":1307,"path":1308,"stem":1309},"Версіонування API","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fapi-versioning","01.csharp\u002F11.aspnet\u002F12.web-api\u002F04.api-versioning",{"title":1311,"path":1312,"stem":1313},"ProblemDetails та структурована обробка помилок","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fproblemdetails-error-handling","01.csharp\u002F11.aspnet\u002F12.web-api\u002F05.problemdetails-error-handling",{"title":1315,"path":1316,"stem":1317},"Фільтри у Web API контексті","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Ffilters-for-api","01.csharp\u002F11.aspnet\u002F12.web-api\u002F06.filters-for-api",{"title":1319,"path":1320,"stem":1321},"Пагінація, фільтрація та сортування","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fpagination-filtering-sorting","01.csharp\u002F11.aspnet\u002F12.web-api\u002F07.pagination-filtering-sorting",{"title":1323,"path":1324,"stem":1325},"HATEOAS та Resource Expansion","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fhateoas-resource-expansion","01.csharp\u002F11.aspnet\u002F12.web-api\u002F08.hateoas-resource-expansion",{"title":1327,"path":1328,"stem":1329},"Гібридна архітектура - Minimal API + Controllers","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fminimal-api-vs-controllers-hybrid","01.csharp\u002F11.aspnet\u002F12.web-api\u002F09.minimal-api-vs-controllers-hybrid",{"title":1331,"path":1332,"stem":1333},"Документація API - Swashbuckle, NSwag та генерація клієнтів","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fapi-documentation-generation","01.csharp\u002F11.aspnet\u002F12.web-api\u002F10.api-documentation-generation",{"title":1335,"path":1336,"stem":1337},"Health Checks та моніторинг API","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fhealth-checks-monitoring","01.csharp\u002F11.aspnet\u002F12.web-api\u002F11.health-checks-monitoring",{"title":1339,"path":1340,"stem":1341},"Підсумковий проєкт - Production-Ready REST API","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fweb-api-project","01.csharp\u002F11.aspnet\u002F12.web-api\u002F12.web-api-project",{"title":1343,"path":1344,"stem":1345},"План курсу: ASP.NET Core Web API (Controllers)","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fplan","01.csharp\u002F11.aspnet\u002F12.web-api\u002Fplan",{"title":1347,"icon":1348,"path":1349,"stem":1350,"children":1351,"page":59},"Моніторинг","i-lucide-activity","\u002Fcsharp\u002Faspnet\u002Fmonitoring","01.csharp\u002F11.aspnet\u002F13.monitoring",[1352,1356,1360],{"title":1353,"path":1354,"stem":1355},"Спостережуваність: від console.log до production-систем","\u002Fcsharp\u002Faspnet\u002Fmonitoring\u002Fobservability-intro","01.csharp\u002F11.aspnet\u002F13.monitoring\u002F01.observability-intro",{"title":1357,"path":1358,"stem":1359},"Health Checks: перший рівень observability","\u002Fcsharp\u002Faspnet\u002Fmonitoring\u002Fhealth-checks","01.csharp\u002F11.aspnet\u002F13.monitoring\u002F02.health-checks",{"title":1361,"path":1362,"stem":1363},"Вбудовані метрики .NET 10 та System.Diagnostics.Metrics","\u002Fcsharp\u002Faspnet\u002Fmonitoring\u002Fdotnet-metrics","01.csharp\u002F11.aspnet\u002F13.monitoring\u002F03.dotnet-metrics",{"title":1365,"icon":1366,"path":1367,"stem":1368,"children":1369,"page":59},"Desktop UI","i-lucide-app-window","\u002Fcsharp\u002Fdesktop-ui","01.csharp\u002F12.desktop-ui",[1370,1374,1378,1382,1386,1390,1394,1398,1402,1406,1410,1414,1418,1422,1426,1430,1434,1438,1442,1446,1450,1454,1458,1462,1466,1470,1474,1478,1482,1486,1490,1494,1498,1502,1506,1510,1514,1518,1522,1526,1530,1534,1538,1542,1546,1550,1554,1558,1562,1566,1570,1574,1578,1582,1586,1590,1594,1598,1602,1606,1610,1614,1618,1622,1626,1630,1634,1638,1642,1646,1650],{"title":1371,"path":1372,"stem":1373},"Що таке десктопна розробка?","\u002Fcsharp\u002Fdesktop-ui\u002Fwhat-is-desktop-dev","01.csharp\u002F12.desktop-ui\u002F01.what-is-desktop-dev",{"title":1375,"path":1376,"stem":1377},"Архітектура WPF — як влаштований графічний інтерфейс","\u002Fcsharp\u002Fdesktop-ui\u002Fwpf-architecture","01.csharp\u002F12.desktop-ui\u002F02.wpf-architecture",{"title":1379,"path":1380,"stem":1381},"Перший WPF-проєкт — від нуля до вікна","\u002Fcsharp\u002Fdesktop-ui\u002Ffirst-wpf-app","01.csharp\u002F12.desktop-ui\u002F03.first-wpf-app",{"title":1383,"path":1384,"stem":1385},"Перший Avalonia-проєкт: WPF для всіх платформ","\u002Fcsharp\u002Fdesktop-ui\u002F03a.first-avalonia-app","01.csharp\u002F12.desktop-ui\u002F03a.first-avalonia-app",{"title":1387,"path":1388,"stem":1389},"XAML: декларативний інтерфейс","\u002Fcsharp\u002Fdesktop-ui\u002Fxaml-basics","01.csharp\u002F12.desktop-ui\u002F04.xaml-basics",{"title":1391,"path":1392,"stem":1393},"Fluent UI у WPF — сучасний дизайн Windows 11","\u002Fcsharp\u002Fdesktop-ui\u002F04a.wpf-fluent-ui","01.csharp\u002F12.desktop-ui\u002F04a.wpf-fluent-ui",{"title":1395,"path":1396,"stem":1397},"WPF UI — сучасна бібліотека Fluent контролів","\u002Fcsharp\u002Fdesktop-ui\u002F04b.wpf-ui-library","01.csharp\u002F12.desktop-ui\u002F04b.wpf-ui-library",{"title":1399,"path":1400,"stem":1401},"HandyControl — велика бібліотека UI контролів для WPF","\u002Fcsharp\u002Fdesktop-ui\u002F04c.handycontrol-library","01.csharp\u002F12.desktop-ui\u002F04c.handycontrol-library",{"title":1403,"path":1404,"stem":1405},"Простори імен та ресурси XAML","\u002Fcsharp\u002Fdesktop-ui\u002Fxaml-namespaces-resources","01.csharp\u002F12.desktop-ui\u002F05.xaml-namespaces-resources",{"title":1407,"path":1408,"stem":1409},"XAML в Avalonia: ключові відмінності від WPF","\u002Fcsharp\u002Fdesktop-ui\u002F05a.avalonia-xaml-differences","01.csharp\u002F12.desktop-ui\u002F05a.avalonia-xaml-differences",{"title":1411,"path":1412,"stem":1413},"Розширення розмітки XAML (Markup Extensions)","\u002Fcsharp\u002Fdesktop-ui\u002Fxaml-markup-extensions","01.csharp\u002F12.desktop-ui\u002F06.xaml-markup-extensions",{"title":1415,"path":1416,"stem":1417},"Панелі Layout: StackPanel, WrapPanel, DockPanel","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-panels-part1","01.csharp\u002F12.desktop-ui\u002F07.layout-panels-part1",{"title":1419,"path":1420,"stem":1421},"Grid, Canvas, UniformGrid","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-panels-part2","01.csharp\u002F12.desktop-ui\u002F07.layout-panels-part2",{"title":1423,"path":1424,"stem":1425},"Просунуті техніки Layout","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-advanced","01.csharp\u002F12.desktop-ui\u002F08.layout-advanced",{"title":1427,"path":1428,"stem":1429},"Адаптивний Layout та найкращі практики","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-responsive","01.csharp\u002F12.desktop-ui\u002F09.layout-responsive",{"title":1431,"path":1432,"stem":1433},"Layout в Avalonia: відмінності та нові можливості","\u002Fcsharp\u002Fdesktop-ui\u002F09a.layout-avalonia","01.csharp\u002F12.desktop-ui\u002F09a.layout-avalonia",{"title":1435,"path":1436,"stem":1437},"Button, Image, ProgressBar та інші базові контроли","\u002Fcsharp\u002Fdesktop-ui\u002Fbasic-controls","01.csharp\u002F12.desktop-ui\u002F10.basic-controls",{"title":1439,"path":1440,"stem":1441},"Контроли в Avalonia: відмінності від WPF","\u002Fcsharp\u002Fdesktop-ui\u002F10a.controls-avalonia","01.csharp\u002F12.desktop-ui\u002F10a.controls-avalonia",{"title":1443,"path":1444,"stem":1445},"Текстові контроли — TextBlock, TextBox, RichTextBox","\u002Fcsharp\u002Fdesktop-ui\u002Ftext-controls","01.csharp\u002F12.desktop-ui\u002F11.text-controls",{"title":1447,"path":1448,"stem":1449},"Контроли вибору — CheckBox, RadioButton, ComboBox, ListBox, DatePicker","\u002Fcsharp\u002Fdesktop-ui\u002Fselection-controls","01.csharp\u002F12.desktop-ui\u002F12.selection-controls",{"title":1451,"path":1452,"stem":1453},"Content Model — GroupBox, Expander, TabControl, StatusBar","\u002Fcsharp\u002Fdesktop-ui\u002Fcontent-controls","01.csharp\u002F12.desktop-ui\u002F13.content-controls",{"title":1455,"path":1456,"stem":1457},"UI\u002FUX принципи десктопних застосунків","\u002Fcsharp\u002Fdesktop-ui\u002F13a.ui-ux-principles","01.csharp\u002F12.desktop-ui\u002F13a.ui-ux-principles",{"title":1459,"path":1460,"stem":1461},"Dependency Properties — Концепція та Value Resolution","\u002Fcsharp\u002Fdesktop-ui\u002Fdependency-properties-part1","01.csharp\u002F12.desktop-ui\u002F14.dependency-properties-part1",{"title":1463,"path":1464,"stem":1465},"Avalonia Property System — StyledProperty та DirectProperty","\u002Fcsharp\u002Fdesktop-ui\u002F14a.avalonia-property-system","01.csharp\u002F12.desktop-ui\u002F14a.avalonia-property-system",{"title":1467,"path":1468,"stem":1469},"Attached Properties — Властивості без меж","\u002Fcsharp\u002Fdesktop-ui\u002Fattached-properties","01.csharp\u002F12.desktop-ui\u002F15.attached-properties",{"title":1471,"path":1472,"stem":1473},"Routed Events — Маршрутизація подій у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Frouted-events","01.csharp\u002F12.desktop-ui\u002F16.routed-events",{"title":1475,"path":1476,"stem":1477},"Data Binding — Від Code-Behind до Декларативності","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-binding-basics-part1","01.csharp\u002F12.desktop-ui\u002F17.data-binding-basics-part1",{"title":1479,"path":1480,"stem":1481},"INotifyPropertyChanged — Живе оновлення UI","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-binding-basics-part2","01.csharp\u002F12.desktop-ui\u002F17.data-binding-basics-part2",{"title":1483,"path":1484,"stem":1485},"Compiled Bindings в Avalonia — Безпека на етапі компіляції","\u002Fcsharp\u002Fdesktop-ui\u002F17a.avalonia-compiled-bindings","01.csharp\u002F12.desktop-ui\u002F17a.avalonia-compiled-bindings",{"title":1487,"path":1488,"stem":1489},"Просунутий Data Binding — ElementName, RelativeSource, MultiBinding","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-binding-advanced","01.csharp\u002F12.desktop-ui\u002F18.data-binding-advanced",{"title":1491,"path":1492,"stem":1493},"Value Converters — Перетворення типів даних у Data Binding","\u002Fcsharp\u002Fdesktop-ui\u002Fvalue-converters","01.csharp\u002F12.desktop-ui\u002F19.value-converters",{"title":1495,"path":1496,"stem":1497},"Data Templates — Візуалізація об'єктів у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-templates","01.csharp\u002F12.desktop-ui\u002F20.data-templates",{"title":1499,"path":1500,"stem":1501},"Collections Binding Part 1 — ObservableCollection та ItemsControl","\u002Fcsharp\u002Fdesktop-ui\u002Fcollections-binding-part1","01.csharp\u002F12.desktop-ui\u002F21.collections-binding-part1",{"title":1503,"path":1504,"stem":1505},"Collections Binding Part 2 — ICollectionView, Filtering, Sorting та Virtualization","\u002Fcsharp\u002Fdesktop-ui\u002Fcollections-binding-part2","01.csharp\u002F12.desktop-ui\u002F21.collections-binding-part2",{"title":1507,"path":1508,"stem":1509},"MVVM Pattern — Від Spaghetti Code до архітектури","\u002Fcsharp\u002Fdesktop-ui\u002Fmvvm-pattern","01.csharp\u002F12.desktop-ui\u002F22.mvvm-pattern",{"title":1511,"path":1512,"stem":1513},"ViewModel Implementation — Від BaseViewModel до валідації","\u002Fcsharp\u002Fdesktop-ui\u002Fviewmodel-implementation","01.csharp\u002F12.desktop-ui\u002F23.viewmodel-implementation",{"title":1515,"path":1516,"stem":1517},"Commands — Від event handlers до декларативних команд","\u002Fcsharp\u002Fdesktop-ui\u002Fcommands","01.csharp\u002F12.desktop-ui\u002F24.commands",{"title":1519,"path":1520,"stem":1521},"MVVM Toolkit — MVVM без boilerplate через Source Generators","\u002Fcsharp\u002Fdesktop-ui\u002Fmvvm-toolkit","01.csharp\u002F12.desktop-ui\u002F25.mvvm-toolkit",{"title":1523,"path":1524,"stem":1525},"Messenger Pattern — Комунікація між ViewModel без прямих посилань","\u002Fcsharp\u002Fdesktop-ui\u002Fmessenger-pattern","01.csharp\u002F12.desktop-ui\u002F26.messenger-pattern",{"title":1527,"path":1528,"stem":1529},"Стилі WPF — CSS для десктопу","\u002Fcsharp\u002Fdesktop-ui\u002Fstyles-basics","01.csharp\u002F12.desktop-ui\u002F27.styles-basics",{"title":1531,"path":1532,"stem":1533},"CSS-like стилі Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002F27a.avalonia-css-styling","01.csharp\u002F12.desktop-ui\u002F27a.avalonia-css-styling",{"title":1535,"path":1536,"stem":1537},"Control Templates — Частина 1. Концепція та TemplateBinding","\u002Fcsharp\u002Fdesktop-ui\u002Fcontrol-templates-part1","01.csharp\u002F12.desktop-ui\u002F28.control-templates-part1",{"title":1539,"path":1540,"stem":1541},"Control Templates — Частина 2. Named Parts та ContentPresenter","\u002Fcsharp\u002Fdesktop-ui\u002Fcontrol-templates-part2","01.csharp\u002F12.desktop-ui\u002F28.control-templates-part2",{"title":1543,"path":1544,"stem":1545},"Control Themes в Avalonia — нова ера стилізації","\u002Fcsharp\u002Fdesktop-ui\u002F28a.avalonia-control-themes","01.csharp\u002F12.desktop-ui\u002F28a.avalonia-control-themes",{"title":1547,"path":1548,"stem":1549},"Triggers та Visual State Manager у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Ftriggers-visual-states","01.csharp\u002F12.desktop-ui\u002F29.triggers-visual-states",{"title":1551,"path":1552,"stem":1553},"Pseudo-classes в Avalonia — замість WPF Triggers","\u002Fcsharp\u002Fdesktop-ui\u002F29a.avalonia-pseudo-classes","01.csharp\u002F12.desktop-ui\u002F29a.avalonia-pseudo-classes",{"title":1555,"path":1556,"stem":1557},"Теми та ресурсні словники у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fresources-themes","01.csharp\u002F12.desktop-ui\u002F30.resources-themes",{"title":1559,"path":1560,"stem":1561},"Avalonia Themes — Fluent Design та система тематизації","\u002Fcsharp\u002Fdesktop-ui\u002F30a.avalonia-themes-fluent","01.csharp\u002F12.desktop-ui\u002F30a.avalonia-themes-fluent",{"title":1563,"path":1564,"stem":1565},"Контроли колекцій — глибоке занурення","\u002Fcsharp\u002Fdesktop-ui\u002Fcollection-controls","01.csharp\u002F12.desktop-ui\u002F31.collection-controls",{"title":1567,"path":1568,"stem":1569},"DataGrid — колонки та базове відображення","\u002Fcsharp\u002Fdesktop-ui\u002Fdatagrid-part1","01.csharp\u002F12.desktop-ui\u002F32.datagrid-part1",{"title":1571,"path":1572,"stem":1573},"DataGrid — сортування, фільтрація, редагування","\u002Fcsharp\u002Fdesktop-ui\u002Fdatagrid-part2","01.csharp\u002F12.desktop-ui\u002F32.datagrid-part2",{"title":1575,"path":1576,"stem":1577},"TreeView та GridView","\u002Fcsharp\u002Fdesktop-ui\u002Ftreeview-listview","01.csharp\u002F12.desktop-ui\u002F33.treeview-listview",{"title":1579,"path":1580,"stem":1581},"Меню, Toolbar, ContextMenu, StatusBar","\u002Fcsharp\u002Fdesktop-ui\u002Fmenus-toolbars","01.csharp\u002F12.desktop-ui\u002F34.menus-toolbars",{"title":1583,"path":1584,"stem":1585},"Навігація та керування вікнами. Частина 1: вікна та сторінки","\u002Fcsharp\u002Fdesktop-ui\u002Fnavigation-windows-part1","01.csharp\u002F12.desktop-ui\u002F35.navigation-windows-part1",{"title":1587,"path":1588,"stem":1589},"Навігація та керування вікнами. Частина 2: MVVM-навігація","\u002Fcsharp\u002Fdesktop-ui\u002Fnavigation-windows-part2","01.csharp\u002F12.desktop-ui\u002F35.navigation-windows-part2",{"title":1591,"path":1592,"stem":1593},"Avalonia — Навігація та діалоги","\u002Fcsharp\u002Fdesktop-ui\u002F35a.avalonia-navigation-dialogs","01.csharp\u002F12.desktop-ui\u002F35a.avalonia-navigation-dialogs",{"title":1595,"path":1596,"stem":1597},"Діалоги та File Pickers у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fdialogs-file-pickers","01.csharp\u002F12.desktop-ui\u002F36.dialogs-file-pickers",{"title":1599,"path":1600,"stem":1601},"UserControl: компонентний підхід у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fuser-controls","01.csharp\u002F12.desktop-ui\u002F37.user-controls",{"title":1603,"path":1604,"stem":1605},"Custom Controls: Lookless Controls у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fcustom-controls","01.csharp\u002F12.desktop-ui\u002F38.custom-controls",{"title":1607,"path":1608,"stem":1609},"Avalonia TemplatedControl — Lookless Controls","\u002Fcsharp\u002Fdesktop-ui\u002F38a.avalonia-templated-controls","01.csharp\u002F12.desktop-ui\u002F38a.avalonia-templated-controls",{"title":1611,"path":1612,"stem":1613},"Анімації у WPF: Storyboard та Easing Functions","\u002Fcsharp\u002Fdesktop-ui\u002Fanimations-transitions","01.csharp\u002F12.desktop-ui\u002F39.animations-transitions",{"title":1615,"path":1616,"stem":1617},"Анімації в Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002F39a.avalonia-animations","01.csharp\u002F12.desktop-ui\u002F39a.avalonia-animations",{"title":1619,"path":1620,"stem":1621},"2D Графіка та Мультимедіа у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fmedia-graphics","01.csharp\u002F12.desktop-ui\u002F40.media-graphics",{"title":1623,"path":1624,"stem":1625},"Dependency Injection у WPF та Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002Fdi-integration","01.csharp\u002F12.desktop-ui\u002F41.di-integration",{"title":1627,"path":1628,"stem":1629},"SQLite та EF Core у десктопних додатках","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-persistence-part1","01.csharp\u002F12.desktop-ui\u002F42.data-persistence-part1",{"title":1631,"path":1632,"stem":1633},"Repository Pattern та Unit of Work","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-persistence-part2","01.csharp\u002F12.desktop-ui\u002F43.data-persistence-part2",{"title":1635,"path":1636,"stem":1637},"Тестування ViewModels","\u002Fcsharp\u002Fdesktop-ui\u002Fviewmodel-testing","01.csharp\u002F12.desktop-ui\u002F44.viewmodel-testing",{"title":1639,"path":1640,"stem":1641},"Avalonia Headless Testing — тестування UI без вікон","\u002Fcsharp\u002Fdesktop-ui\u002F44a.avalonia-headless-testing","01.csharp\u002F12.desktop-ui\u002F44a.avalonia-headless-testing",{"title":1643,"path":1644,"stem":1645},"Кросплатформна розробка з Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002Favalonia-cross-platform","01.csharp\u002F12.desktop-ui\u002F45.avalonia-cross-platform",{"title":1647,"path":1648,"stem":1649},"Пакування та розгортання Avalonia додатків","\u002Fcsharp\u002Fdesktop-ui\u002Favalonia-packaging-deployment","01.csharp\u002F12.desktop-ui\u002F46.avalonia-packaging-deployment",{"title":1651,"path":1652,"stem":1653},"Розгортання WPF застосунків","\u002Fcsharp\u002Fdesktop-ui\u002Fwpf-packaging-deployment","01.csharp\u002F12.desktop-ui\u002F47.wpf-packaging-deployment",{"title":1655,"icon":658,"path":1656,"stem":1657,"children":1658,"page":59},"Network Programming","\u002Fcsharp\u002Fnetwork-programming","01.csharp\u002F13.network-programming",[1659,1663,1667,1671,1675,1679,1683,1687,1691,1695,1699],{"title":1660,"path":1661,"stem":1662},"Основи комп'ютерних мереж","\u002Fcsharp\u002Fnetwork-programming\u002Ffoundations","01.csharp\u002F13.network-programming\u002F01.foundations",{"title":1664,"path":1665,"stem":1666},"Модель OSI та стек TCP\u002FIP","\u002Fcsharp\u002Fnetwork-programming\u002Fosi-model","01.csharp\u002F13.network-programming\u002F02.osi-model",{"title":1668,"path":1669,"stem":1670},"IP-протокол та адресація","\u002Fcsharp\u002Fnetwork-programming\u002Fip-addressing","01.csharp\u002F13.network-programming\u002F03.ip-addressing",{"title":1672,"path":1673,"stem":1674},"UDP — протокол без з'єднання","\u002Fcsharp\u002Fnetwork-programming\u002Fudp","01.csharp\u002F13.network-programming\u002F05.udp",{"title":1676,"path":1677,"stem":1678},"UDP Broadcast та Multicast","\u002Fcsharp\u002Fnetwork-programming\u002Fudp-broadcast-multicast","01.csharp\u002F13.network-programming\u002F06.udp-broadcast-multicast",{"title":1680,"path":1681,"stem":1682},"HTTP — протокол вебу","\u002Fcsharp\u002Fnetwork-programming\u002Fhttp-fundamentals","01.csharp\u002F13.network-programming\u002F07.http-fundamentals",{"title":1684,"path":1685,"stem":1686},"HttpListener — вбудований HTTP-сервер .NET","\u002Fcsharp\u002Fnetwork-programming\u002F07a.http-listener","01.csharp\u002F13.network-programming\u002F07a.http-listener",{"title":1688,"path":1689,"stem":1690},"HTTP Advanced — cookies, аутентифікація та HTTPS","\u002Fcsharp\u002Fnetwork-programming\u002Fhttp-advanced","01.csharp\u002F13.network-programming\u002F08.http-advanced",{"title":1692,"path":1693,"stem":1694},"SMTP та протоколи електронної пошти","\u002Fcsharp\u002Fnetwork-programming\u002Fsmtp","01.csharp\u002F13.network-programming\u002F09.smtp",{"title":1696,"path":1697,"stem":1698},"WebSocket — повнодуплексний протокол реального часу","\u002Fcsharp\u002Fnetwork-programming\u002Fwebsockets","01.csharp\u002F13.network-programming\u002F10.websockets",{"title":1700,"path":1701,"stem":1702},"TLS\u002FSSL — криптографічний захист мережевих з'єднань","\u002Fcsharp\u002Fnetwork-programming\u002Ftls-ssl","01.csharp\u002F13.network-programming\u002F11.tls-ssl",{"title":1704,"path":1705,"stem":1706},"C# & .NET: The Ultimate Roadmap","\u002Fcsharp\u002Froadmap","01.csharp\u002Froadmap",{"title":1708,"icon":1709,"path":1710,"stem":1711,"children":1712,"page":59},"C++","i-devicon-cplusplus","\u002Fcpp","02.cpp",[1713,1717,1721,1725,1729,1733,1737,1741,1745,1748,1752,1756,1760,1764,1768,1772,1776,1780,1784,1788,1792,1796,1800,1804,1808,1812,1816,1820,1824,1828,1832,1836,1840,1844,1848,1852,1856,1860,1864,1868,1872,1876,1880,1884,1888,1892,1896,1900,1904,1908],{"title":1714,"path":1715,"stem":1716},"Вступ у програмування та алгоритми","\u002Fcpp\u002Fintro-algorithms","02.cpp\u002F01.intro-algorithms",{"title":1718,"path":1719,"stem":1720},"Code Style: угоди про оформлення коду","\u002Fcpp\u002Fcode-style","02.cpp\u002F02.code-style",{"title":1722,"path":1723,"stem":1724},"Середовище розробки та перший проєкт","\u002Fcpp\u002Fide-setup","02.cpp\u002F03.ide-setup",{"title":1726,"path":1727,"stem":1728},"Вивід даних на екран","\u002Fcpp\u002Fdata-output","02.cpp\u002F04.data-output",{"title":1730,"path":1731,"stem":1732},"Типи даних, змінні та константи","\u002Fcpp\u002Fdata-types-variables","02.cpp\u002F05.data-types-variables",{"title":1734,"path":1735,"stem":1736},"Ввід даних з клавіатури","\u002Fcpp\u002Fdata-input","02.cpp\u002F06.data-input",{"title":1738,"path":1739,"stem":1740},"Оператори, перетворення типів та логічні операції","\u002Fcpp\u002Foperators-type-conversion","02.cpp\u002F07.operators-type-conversion",{"title":1742,"path":1743,"stem":1744},"Цикли","\u002Fcpp\u002Floops","02.cpp\u002F08.loops",{"title":32,"path":1746,"stem":1747},"\u002Fcpp\u002Farrays","02.cpp\u002F09.arrays",{"title":1749,"path":1750,"stem":1751},"Алгоритми сортування та аналіз складності","\u002Fcpp\u002Fsorting","02.cpp\u002F10.sorting",{"title":1753,"path":1754,"stem":1755},"Алгоритми пошуку","\u002Fcpp\u002Fsearching","02.cpp\u002F11.searching",{"title":1757,"path":1758,"stem":1759},"Функції: основи","\u002Fcpp\u002Ffunctions-basics","02.cpp\u002F12.functions-basics",{"title":1761,"path":1762,"stem":1763},"Функції: прототипи, область видимості та додаткові можливості","\u002Fcpp\u002Ffunctions-scope","02.cpp\u002F13.functions-scope",{"title":1765,"path":1766,"stem":1767},"Функції: перевантаження та шаблони","\u002Fcpp\u002Ffunctions-overloading-templates","02.cpp\u002F14.functions-overloading-templates",{"title":1769,"path":1770,"stem":1771},"Вказівники: основи","\u002Fcpp\u002Fpointers-basics","02.cpp\u002F15.pointers-basics",{"title":1773,"path":1774,"stem":1775},"Посилання (References)","\u002Fcpp\u002Freferences","02.cpp\u002F16.references",{"title":1777,"path":1778,"stem":1779},"Вказівники, const і масиви","\u002Fcpp\u002Fpointers-const-arrays","02.cpp\u002F17.pointers-const-arrays",{"title":1781,"path":1782,"stem":1783},"Адресна арифметика","\u002Fcpp\u002Fpointer-arithmetic","02.cpp\u002F18.pointer-arithmetic",{"title":1785,"path":1786,"stem":1787},"Динамічна пам'ять","\u002Fcpp\u002Fdynamic-memory","02.cpp\u002F19.dynamic-memory",{"title":1789,"path":1790,"stem":1791},"Вказівники типу void","\u002Fcpp\u002Fvoid-pointers","02.cpp\u002F20.void-pointers",{"title":1793,"path":1794,"stem":1795},"Вказівники на вказівники","\u002Fcpp\u002Fpointers-to-pointers","02.cpp\u002F21.pointers-to-pointers",{"title":1797,"path":1798,"stem":1799},"Оператор доступу до членів через вказівник (->)","\u002Fcpp\u002Fmember-access-operator","02.cpp\u002F22.member-access-operator",{"title":1801,"path":1802,"stem":1803},"Цикл for-each (Range-based for)","\u002Fcpp\u002Fforeach-loop","02.cpp\u002F23.foreach-loop",{"title":1805,"path":1806,"stem":1807},"Вказівники на функції","\u002Fcpp\u002Ffunction-pointers","02.cpp\u002F24.function-pointers",{"title":1809,"path":1810,"stem":1811},"Лямбда-вирази","\u002Fcpp\u002Flambdas","02.cpp\u002F25.lambdas",{"title":1813,"path":1814,"stem":1815},"Лямбда-захоплення","\u002Fcpp\u002Flambda-captures","02.cpp\u002F26.lambda-captures",{"title":1817,"path":1818,"stem":1819},"Еліпсис","\u002Fcpp\u002Fellipsis","02.cpp\u002F27.ellipsis",{"title":1821,"path":1822,"stem":1823},"Безпечні альтернативи еліпсису","\u002Fcpp\u002F27a.ellipsis","02.cpp\u002F27a.ellipsis",{"title":1825,"path":1826,"stem":1827},"Аргументи командного рядка","\u002Fcpp\u002Fcommand-line-arguments","02.cpp\u002F28.command-line-arguments",{"title":1829,"path":1830,"stem":1831},"Перерахування (enum)","\u002Fcpp\u002Fenum","02.cpp\u002F29.enum",{"title":1833,"path":1834,"stem":1835},"Класи-перерахування (enum class)","\u002Fcpp\u002Fenum-class","02.cpp\u002F30.enum-class",{"title":1837,"path":1838,"stem":1839},"Псевдоніми типів (typedef і using)","\u002Fcpp\u002Ftype-aliases","02.cpp\u002F31.type-aliases",{"title":1841,"path":1842,"stem":1843},"Системи числення та двійкова арифметика","\u002Fcpp\u002Fnumber-systems","02.cpp\u002F32.number-systems",{"title":1845,"path":1846,"stem":1847},"Структури (struct): агрегування даних","\u002Fcpp\u002Fstruct","02.cpp\u002F33.struct",{"title":1849,"path":1850,"stem":1851},"Структури у функціях","\u002Fcpp\u002Fstruct-functions","02.cpp\u002F34.struct-functions",{"title":1853,"path":1854,"stem":1855},"Масиви структур і вкладені структури","\u002Fcpp\u002Fstruct-arrays","02.cpp\u002F35.struct-arrays",{"title":1857,"path":1858,"stem":1859},"Патерни struct та межі застосування","\u002Fcpp\u002Fstruct-patterns","02.cpp\u002F36.struct-patterns",{"title":1861,"path":1862,"stem":1863},"Символи та таблиця ASCII","\u002Fcpp\u002Fascii-characters","02.cpp\u002F37.ascii-characters",{"title":1865,"path":1866,"stem":1867},"Unicode та кодування UTF","\u002Fcpp\u002Funicode-utf","02.cpp\u002F38.unicode-utf",{"title":1869,"path":1870,"stem":1871},"C-style рядки","\u002Fcpp\u002Fc-strings","02.cpp\u002F39.c-strings",{"title":1873,"path":1874,"stem":1875},"Вступ до std::string","\u002Fcpp\u002Fstd-string-intro","02.cpp\u002F40.std-string-intro",{"title":1877,"path":1878,"stem":1879},"Довжина, ємність та доступ до символів std::string","\u002Fcpp\u002Fstd-string-capacity-access","02.cpp\u002F41.std-string-capacity-access",{"title":1881,"path":1882,"stem":1883},"Модифікація std::string: присвоювання, додавання, вставка, видалення та заміна","\u002Fcpp\u002Fstd-string-modification","02.cpp\u002F42.std-string-modification",{"title":1885,"path":1886,"stem":1887},"Пошук у std::string: find, npos та практичні патерни","\u002Fcpp\u002Fstd-string-search","02.cpp\u002F43.std-string-search",{"title":1889,"path":1890,"stem":1891},"std::string_view: невласницький погляд на рядок без копіювання","\u002Fcpp\u002Fstd-string-view","02.cpp\u002F44.std-string-view",{"title":1893,"path":1894,"stem":1895},"Об'єднання (union): один блок пам'яті, кілька інтерпретацій","\u002Fcpp\u002Funion","02.cpp\u002F45.union",{"title":1897,"path":1898,"stem":1899},"Організація коду: файли, препроцесор, простори імен","\u002Fcpp\u002Fmultifile-programs","02.cpp\u002F46.multifile-programs",{"title":1901,"path":1902,"stem":1903},"Робота з файлами: C-стиль (stdio.h)","\u002Fcpp\u002Fc-style-files","02.cpp\u002F47.c-style-files",{"title":1905,"path":1906,"stem":1907},"Робота з файлами: C++-стиль (fstream)","\u002Fcpp\u002Fcpp-style-files","02.cpp\u002F48.cpp-style-files",{"title":1909,"path":1910,"stem":1911},"План навчання: Курс C++ — Продовження (Статті 29–60+)","\u002Fcpp\u002Fcurriculum-plan","02.cpp\u002Fcurriculum-plan",{"title":1913,"icon":1914,"path":1915,"stem":1916,"children":1917,"page":59},"JavaScript","i-devicon-javascript","\u002Fjavascript","03.javascript",[1918,1944,1998,2020,2324,2362],{"title":1919,"icon":1920,"path":1921,"stem":1922,"children":1923,"page":59},"Events","i-lucide-mouse-pointer-click","\u002Fjavascript\u002Fevents","03.javascript\u002F01.events",[1924,1928,1932,1936,1940],{"title":1925,"path":1926,"stem":1927},"Вступ до подій браузера","\u002Fjavascript\u002Fevents\u002Fintro","03.javascript\u002F01.events\u002F01.intro",{"title":1929,"path":1930,"stem":1931},"Бульбашковий механізм (Bubbling) та занурення (Capturing)","\u002Fjavascript\u002Fevents\u002Fbubbling-capturing","03.javascript\u002F01.events\u002F02.bubbling-capturing",{"title":1933,"path":1934,"stem":1935},"Делегування подій (Event Delegation)","\u002Fjavascript\u002Fevents\u002Fdelegate-events","03.javascript\u002F01.events\u002F03.delegate-events",{"title":1937,"path":1938,"stem":1939},"Типові дії браузера та preventDefault()","\u002Fjavascript\u002Fevents\u002Fprevent-default","03.javascript\u002F01.events\u002F04.prevent-default",{"title":1941,"path":1942,"stem":1943},"Запуск користувацьких подій (Custom Events)","\u002Fjavascript\u002Fevents\u002Fcustom-events","03.javascript\u002F01.events\u002F05.custom-events",{"title":1945,"icon":1946,"path":1947,"stem":1948,"children":1949,"page":59},"Network","i-lucide-globe","\u002Fjavascript\u002Fnetwork","03.javascript\u002F02.network",[1950,1954,1958,1962,1966,1970,1974,1978,1982,1986,1990,1994],{"title":1951,"path":1952,"stem":1953},"Fetch API - Сучасний підхід до HTTP-запитів","\u002Fjavascript\u002Fnetwork\u002F01-fetch-api","03.javascript\u002F02.network\u002F01-fetch-api",{"title":1955,"path":1956,"stem":1957},"FormData - Робота з формами та файлами","\u002Fjavascript\u002Fnetwork\u002F02-formdata","03.javascript\u002F02.network\u002F02-formdata",{"title":1959,"path":1960,"stem":1961},"Відстеження прогресу завантаження","\u002Fjavascript\u002Fnetwork\u002F03-download-progress","03.javascript\u002F02.network\u002F03-download-progress",{"title":1963,"path":1964,"stem":1965},"Переривання fetch-запитів","\u002Fjavascript\u002Fnetwork\u002F04-abort-requests","03.javascript\u002F02.network\u002F04-abort-requests",{"title":1967,"path":1968,"stem":1969},"CORS - Запити між різними джерелами","\u002Fjavascript\u002Fnetwork\u002F05-cors","03.javascript\u002F02.network\u002F05-cors",{"title":1971,"path":1972,"stem":1973},"Fetch API - Повний довідник опцій","\u002Fjavascript\u002Fnetwork\u002F06-fetch-options","03.javascript\u002F02.network\u002F06-fetch-options",{"title":1975,"path":1976,"stem":1977},"URL Objects - Робота з посиланнями","\u002Fjavascript\u002Fnetwork\u002F07-url-objects","03.javascript\u002F02.network\u002F07-url-objects",{"title":1979,"path":1980,"stem":1981},"XMLHttpRequest - AJAX та низькорівневі запити","\u002Fjavascript\u002Fnetwork\u002F08-xmlhttprequest","03.javascript\u002F02.network\u002F08-xmlhttprequest",{"title":1983,"path":1984,"stem":1985},"Відновлюване завантаження файлів","\u002Fjavascript\u002Fnetwork\u002F09-resumable-upload","03.javascript\u002F02.network\u002F09-resumable-upload",{"title":1987,"path":1988,"stem":1989},"Cookies, document.cookie та світ після \"Cookiepocalypse\"","\u002Fjavascript\u002Fnetwork\u002F10-cookies","03.javascript\u002F02.network\u002F10-cookies",{"title":1991,"path":1992,"stem":1993},"js-cookie: Керування Cookies без Болю","\u002Fjavascript\u002Fnetwork\u002F11-js-cookie","03.javascript\u002F02.network\u002F11-js-cookie",{"title":1995,"path":1996,"stem":1997},"Axios: Потужний HTTP-клієнт для JavaScript","\u002Fjavascript\u002Fnetwork\u002F12-axios","03.javascript\u002F02.network\u002F12-axios",{"title":1999,"icon":2000,"path":2001,"stem":2002,"children":2003,"page":59},"Bom","i-lucide-monitor","\u002Fjavascript\u002Fbom","03.javascript\u002F03.bom",[2004,2008,2012,2016],{"title":2005,"path":2006,"stem":2007},"LocalStorage, SessionStorage та patterns збереження даних","\u002Fjavascript\u002Fbom\u002F01-localstorage","03.javascript\u002F03.bom\u002F01-localstorage",{"title":2009,"path":2010,"stem":2011},"Location Object - Керування адресою сторінки","\u002Fjavascript\u002Fbom\u002F02-location-object","03.javascript\u002F03.bom\u002F02-location-object",{"title":2013,"path":2014,"stem":2015},"History API - Керування історією браузера","\u002Fjavascript\u002Fbom\u002F03-history-api","03.javascript\u002F03.bom\u002F03-history-api",{"title":2017,"path":2018,"stem":2019},"Navigator Object - Ідентифікація та Можливості Пристрою","\u002Fjavascript\u002Fbom\u002F04-navigator-object","03.javascript\u002F03.bom\u002F04-navigator-object",{"title":2021,"icon":2022,"path":2023,"stem":2024,"children":2025},"React","i-devicon-react","\u002Fjavascript\u002Freact","03.javascript\u002F04.react\u002Findex",[2026,2027,2031,2035,2039,2043,2106,2141,2293],{"title":2021,"path":2023,"stem":2024},{"title":2028,"path":2029,"stem":2030},"Робота з Формами в React","\u002Fjavascript\u002Freact\u002Freact-forms","03.javascript\u002F04.react\u002F01.react-forms",{"title":2032,"path":2033,"stem":2034},"React Hook Form: Професійна Робота з Формами","\u002Fjavascript\u002Freact\u002Freact-hook-form","03.javascript\u002F04.react\u002F02.react-hook-form",{"title":2036,"path":2037,"stem":2038},"React Hook Form: Глибоке Розуміння Архітектури та Оптимізації","\u002Fjavascript\u002Freact\u002Freact-hook-form-new","03.javascript\u002F04.react\u002F02.react-hook-form-new",{"title":2040,"path":2041,"stem":2042},"Axios та React: Професійна Архітектура Запитів","\u002Fjavascript\u002Freact\u002Fdata-fetching-axios","03.javascript\u002F04.react\u002F03.data-fetching-axios",{"title":2044,"icon":132,"path":2045,"stem":2046,"children":2047},"Tanstack Query","\u002Fjavascript\u002Freact\u002Ftanstack-query","03.javascript\u002F04.react\u002F04.tanstack-query\u002Findex",[2048,2050,2054,2058,2062,2066,2070,2074,2078,2082,2086,2090,2094,2098,2102],{"title":2049,"path":2045,"stem":2046},"TanStack Query: Майстерність Керування Станом Сервера",{"title":2051,"path":2052,"stem":2053},"Парадигма Server State: Чому useEffect недостатньо","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fserver-state-paradigm","03.javascript\u002F04.react\u002F04.tanstack-query\u002F01.server-state-paradigm",{"title":2055,"path":2056,"stem":2057},"Встановлення та Налаштування: Фундамент","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Finstallation-and-devtools","03.javascript\u002F04.react\u002F04.tanstack-query\u002F02.installation-and-devtools",{"title":2059,"path":2060,"stem":2061},"Основи Запитів та Магія Ключів","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fquery-basics-and-keys","03.javascript\u002F04.react\u002F04.tanstack-query\u002F03.query-basics-and-keys",{"title":2063,"path":2064,"stem":2065},"Синхронізація Даних: Життєвий Цикл Запиту","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fdata-synchronization","03.javascript\u002F04.react\u002F04.tanstack-query\u002F04.data-synchronization",{"title":2067,"path":2068,"stem":2069},"Мутації та Інвалідація: Зміна Даних","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fmutations-and-invalidation","03.javascript\u002F04.react\u002F04.tanstack-query\u002F05.mutations-and-invalidation",{"title":2071,"path":2072,"stem":2073},"Оптимістичні Оновлення: Швидше за Світло","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Foptimistic-updates","03.javascript\u002F04.react\u002F04.tanstack-query\u002F06.optimistic-updates",{"title":2075,"path":2076,"stem":2077},"Пагінація та Infinite Scroll","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fpagination-and-load-more","03.javascript\u002F04.react\u002F04.tanstack-query\u002F07.pagination-and-load-more",{"title":2079,"path":2080,"stem":2081},"Просунуті Патерни та Оптимізація","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fadvanced-patterns","03.javascript\u002F04.react\u002F04.tanstack-query\u002F08.advanced-patterns",{"title":2083,"path":2084,"stem":2085},"Архітектура та Best Practices","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Farchitecture-and-best-practices","03.javascript\u002F04.react\u002F04.tanstack-query\u002F09.architecture-and-best-practices",{"title":2087,"path":2088,"stem":2089},"Server-Side Rendering (SSR) та Гідратація","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fserver-side-rendering","03.javascript\u002F04.react\u002F04.tanstack-query\u002F10.server-side-rendering",{"title":2091,"path":2092,"stem":2093},"Стратегії Тестування","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Ftesting-strategies","03.javascript\u002F04.react\u002F04.tanstack-query\u002F11.testing-strategies",{"title":2095,"path":2096,"stem":2097},"Аутентифікація та Обробка Помилок","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fauthentication-and-errors","03.javascript\u002F04.react\u002F04.tanstack-query\u002F12.authentication-and-errors",{"title":2099,"path":2100,"stem":2101},"React Suspense та Майбутнє","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Freact-suspense","03.javascript\u002F04.react\u002F04.tanstack-query\u002F13.react-suspense",{"title":2103,"path":2104,"stem":2105},"Глибоке Занурення в Продуктивність","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fperformance-deep-dive","03.javascript\u002F04.react\u002F04.tanstack-query\u002F14.performance-deep-dive",{"title":2107,"icon":2022,"path":2108,"stem":2109,"children":2110},"React Router","\u002Fjavascript\u002Freact\u002Freact-router","03.javascript\u002F04.react\u002F05.react-router\u002Findex",[2111,2113,2117,2121,2125,2129,2133,2137],{"title":2112,"path":2108,"stem":2109},"React Router: Навігаційна система сучасного вебу",{"title":2114,"path":2115,"stem":2116},"Налаштування та Базовий Роутинг","\u002Fjavascript\u002Freact\u002Freact-router\u002Fsetup-and-basic-routing","03.javascript\u002F04.react\u002F05.react-router\u002F01.setup-and-basic-routing",{"title":2118,"path":2119,"stem":2120},"Динамічна Навігація","\u002Fjavascript\u002Freact\u002Freact-router\u002Fnavigation-and-links","03.javascript\u002F04.react\u002F05.react-router\u002F02.navigation-and-links",{"title":2122,"path":2123,"stem":2124},"Вкладені Маршрути та Макети","\u002Fjavascript\u002Freact\u002Freact-router\u002Fnested-routes-and-layouts","03.javascript\u002F04.react\u002F05.react-router\u002F03.nested-routes-and-layouts",{"title":2126,"path":2127,"stem":2128},"Динамічні Маршрути та Параметри","\u002Fjavascript\u002Freact\u002Freact-router\u002Fdynamic-routing","03.javascript\u002F04.react\u002F05.react-router\u002F04.dynamic-routing",{"title":2130,"path":2131,"stem":2132},"Data APIs: Loaders та Actions","\u002Fjavascript\u002Freact\u002Freact-router\u002Fdata-loading","03.javascript\u002F04.react\u002F05.react-router\u002F05.data-loading",{"title":2134,"path":2135,"stem":2136},"Просунуті Патерни","\u002Fjavascript\u002Freact\u002Freact-router\u002Fadvanced-patterns","03.javascript\u002F04.react\u002F05.react-router\u002F06.advanced-patterns",{"title":2138,"path":2139,"stem":2140},"Legacy Routing: Компонентний підхід","\u002Fjavascript\u002Freact\u002Freact-router\u002Flegacy-routing","03.javascript\u002F04.react\u002F05.react-router\u002F07.legacy-routing",{"title":2142,"icon":132,"path":2143,"stem":2144,"children":2145},"Redux","\u002Fjavascript\u002Freact\u002Fredux","03.javascript\u002F04.react\u002F06.redux\u002Findex",[2146,2148,2164,2193,2202,2223,2239,2268],{"title":2147,"path":2143,"stem":2144},"Redux: Еволюція управління станом",{"title":14,"icon":15,"path":2149,"stem":2150,"children":2151,"page":59},"\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals",[2152,2156,2160],{"title":2153,"path":2154,"stem":2155},"Вступ до State Management","\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals\u002Fintro-state-management","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals\u002F01.intro-state-management",{"title":2157,"path":2158,"stem":2159},"Філософія Redux та Три Принципи","\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals\u002Fredux-philosophy","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals\u002F02.redux-philosophy",{"title":2161,"path":2162,"stem":2163},"Чисті функції та Іммутабельність","\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals\u002Fpure-functions-immutability","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals\u002F03.pure-functions-immutability",{"title":2165,"icon":132,"path":2166,"stem":2167,"children":2168,"page":59},"Classic Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux",[2169,2173,2177,2181,2185,2189],{"title":2170,"path":2171,"stem":2172},"Створення Store (Classic Redux)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Fstore-setup","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F01.store-setup",{"title":2174,"path":2175,"stem":2176},"Actions, Constants та Action Creators","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Factions-constants","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F02.actions-constants",{"title":2178,"path":2179,"stem":2180},"Логіка Reducers","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Freducers","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F03.reducers",{"title":2182,"path":2183,"stem":2184},"Комбінування Reducers (Root Reducer)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Fdata-flow","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F04.data-flow",{"title":2186,"path":2187,"stem":2188},"Підключення до React (React-Redux)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Freact-redux-connection","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F05.react-redux-connection",{"title":2190,"path":2191,"stem":2192},"Middleware та Асинхронність (Redux Thunk)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Fmiddleware-thunk","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F06.middleware-thunk",{"title":2194,"icon":132,"path":2195,"stem":2196,"children":2197,"page":59},"Transition To Rtk","\u002Fjavascript\u002Freact\u002Fredux\u002Ftransition-to-rtk","03.javascript\u002F04.react\u002F06.redux\u002F03.transition-to-rtk",[2198],{"title":2199,"path":2200,"stem":2201},"Проблеми класичного Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Ftransition-to-rtk\u002Fproblems-with-classic","03.javascript\u002F04.react\u002F06.redux\u002F03.transition-to-rtk\u002F01.problems-with-classic",{"title":2203,"icon":132,"path":2204,"stem":2205,"children":2206,"page":59},"Redux Toolkit","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit",[2207,2211,2215,2219],{"title":2208,"path":2209,"stem":2210},"Налаштування Store з configureStore","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fconfigure-store","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F01.configure-store",{"title":2212,"path":2213,"stem":2214},"createSlice: Революція в Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fcreate-slice","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F02.create-slice",{"title":2216,"path":2217,"stem":2218},"Асинхронність з createAsyncThunk","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fasync-thunks","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F03.async-thunks",{"title":2220,"path":2221,"stem":2222},"04. Entity Adapter: Керування нормалізованим станом","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fentity-adapter","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F04.entity-adapter",{"title":2224,"icon":92,"path":2225,"stem":2226,"children":2227,"page":59},"Advanced","\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced",[2228,2232,2236],{"title":2229,"path":2230,"stem":2231},"Мемоізація та Селектори: Повний Гайд по Reselect","\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced\u002Fselectors-reselect","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced\u002F01.selectors-reselect",{"title":2233,"path":2234,"stem":2235},"RTK Query: Архітектура Серверного Кешу","\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced\u002Frtk-query-intro","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced\u002F02.rtk-query-intro",{"title":2083,"path":2237,"stem":2238},"\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced\u002Farchitecture-best-practices","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced\u002F03.architecture-best-practices",{"title":2240,"icon":132,"path":2241,"stem":2242,"children":2243,"page":59},"Project Kanban","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban",[2244,2248,2252,2256,2260,2264],{"title":2245,"path":2246,"stem":2247},"Проєкт: Kanban Board (Trello Clone)","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fproject-overview","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F01.project-overview",{"title":2249,"path":2250,"stem":2251},"Налаштування та Типізація","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fsetup-and-types","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F02.setup-and-types",{"title":2253,"path":2254,"stem":2255},"Board Slice: Серце Дошки","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fboard-slice","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F03.board-slice",{"title":2257,"path":2258,"stem":2259},"Логіка Drag & Drop","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fdrag-and-drop-logic","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F04.drag-and-drop-logic",{"title":2261,"path":2262,"stem":2263},"Інтеграція з RTK Query","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Frtk-query-integration","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F05.rtk-query-integration",{"title":2265,"path":2266,"stem":2267},"Optimistic Updates","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Foptimistic-updates","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F06.optimistic-updates",{"title":2269,"icon":132,"path":2270,"stem":2271,"children":2272,"page":59},"Testing","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting","03.javascript\u002F04.react\u002F06.redux\u002F07.testing",[2273,2277,2281,2285,2289],{"title":2274,"path":2275,"stem":2276},"Тестування Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Fintro-testing","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F01.intro-testing",{"title":2278,"path":2279,"stem":2280},"Тестування Reducers","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-reducers","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F02.testing-reducers",{"title":2282,"path":2283,"stem":2284},"Тестування Селекторів","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-selectors","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F03.testing-selectors",{"title":2286,"path":2287,"stem":2288},"Тестування Компонентів (Integration)","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-components","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F04.testing-components",{"title":2290,"path":2291,"stem":2292},"Тестування Async Thunks","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-thunks","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F05.testing-thunks",{"title":2294,"icon":132,"path":2295,"stem":2296,"children":2297},"Ui Libraries","\u002Fjavascript\u002Freact\u002Fui-libraries","03.javascript\u002F04.react\u002F07.ui-libraries\u002Findex",[2298,2300,2304,2308,2312,2316,2320],{"title":2299,"path":2295,"stem":2296},"UI Бібліотеки в React",{"title":2301,"path":2302,"stem":2303},"Вступ до UI Бібліотек: Навіщо Винаходити Велосипед Двічі?","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fintroduction-to-ui-libraries","03.javascript\u002F04.react\u002F07.ui-libraries\u002F01.introduction-to-ui-libraries",{"title":2305,"path":2306,"stem":2307},"Філософія shadcn\u002Fui: \"Not a Component Library\"","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-philosophy","03.javascript\u002F04.react\u002F07.ui-libraries\u002F02.shadcn-philosophy",{"title":2309,"path":2310,"stem":2311},"Установка та Налаштування shadcn\u002Fui","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-installation","03.javascript\u002F04.react\u002F07.ui-libraries\u002F03.shadcn-installation",{"title":2313,"path":2314,"stem":2315},"Базові Компоненти shadcn\u002Fui: Фундамент Інтерфейсу","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-components-basics","03.javascript\u002F04.react\u002F07.ui-libraries\u002F04.shadcn-components-basics",{"title":2317,"path":2318,"stem":2319},"Компоненти Форм: Побудова Інтерактивних Form","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-components-forms","03.javascript\u002F04.react\u002F07.ui-libraries\u002F05.shadcn-components-forms",{"title":2321,"path":2322,"stem":2323},"Складні Компоненти: Dialog, Dropdown, Table та Command","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-components-advanced","03.javascript\u002F04.react\u002F07.ui-libraries\u002F06.shadcn-components-advanced",{"title":2325,"icon":2326,"path":2327,"stem":2328,"children":2329,"page":59},"TypeScript","i-devicon-typescript","\u002Fjavascript\u002Ftypescript","03.javascript\u002F05.typescript",[2330,2334,2338,2342,2346,2350,2354,2358],{"title":2331,"path":2332,"stem":2333},"TypeScript: Броня для вашого коду","\u002Fjavascript\u002Ftypescript\u002Fintro-and-basic-types","03.javascript\u002F05.typescript\u002F01.intro-and-basic-types",{"title":2335,"path":2336,"stem":2337},"Майстерність Моделювання Даних: Інтерфейси та Просунуті Типи","\u002Fjavascript\u002Ftypescript\u002Finterfaces-and-advanced-types","03.javascript\u002F05.typescript\u002F02.interfaces-and-advanced-types",{"title":2339,"path":2340,"stem":2341},"Алхімія Типів: Generics та Utility Types","\u002Fjavascript\u002Ftypescript\u002Fgenerics-and-utilities","03.javascript\u002F05.typescript\u002F03.generics-and-utilities",{"title":2343,"path":2344,"stem":2345},"Архітектура та Шаблони: Класи в TypeScript","\u002Fjavascript\u002Ftypescript\u002Fclasses-and-oop","03.javascript\u002F05.typescript\u002F04.classes-and-oop",{"title":2347,"path":2348,"stem":2349},"Продакшн та Екосистема: Advanced Config & Workflow","\u002Fjavascript\u002Ftypescript\u002Fadvanced-patterns-and-config","03.javascript\u002F05.typescript\u002F05.advanced-patterns-and-config",{"title":2351,"path":2352,"stem":2353},"TypeScript у світі React","\u002Fjavascript\u002Ftypescript\u002Freact-basics","03.javascript\u002F05.typescript\u002F06.react-basics",{"title":2355,"path":2356,"stem":2357},"React + TypeScript: Продвинуті патерни","\u002Fjavascript\u002Ftypescript\u002Freact-advanced","03.javascript\u002F05.typescript\u002F07.react-advanced",{"title":2359,"path":2360,"stem":2361},"React + TypeScript: Екосистема та бібліотеки","\u002Fjavascript\u002Ftypescript\u002Freact-ecosystem","03.javascript\u002F05.typescript\u002F08.react-ecosystem",{"title":2363,"path":2364,"stem":2365},"Atomic Design","\u002Fjavascript\u002Fatomic-design","03.javascript\u002F2.atomic-design",{"title":2367,"icon":2368,"path":2369,"stem":2370,"children":2371,"page":59},"Java","i-devicon-java","\u002Fjava","04.java",[2372,2375,2378,2382,2386,2390,2394],{"title":162,"path":2373,"stem":2374},"\u002Fjava\u002Fdata-mapper-part1","04.java\u002F01.data-mapper-part1",{"title":166,"path":2376,"stem":2377},"\u002Fjava\u002Fdata-mapper-part2","04.java\u002F02.data-mapper-part2",{"title":2379,"path":2380,"stem":2381},"Service Layer: Організація бізнес-логіки","\u002Fjava\u002Fservice-layer","04.java\u002F03.service-layer",{"title":2383,"path":2384,"stem":2385},"Rich Domain Model та State Pattern","\u002Fjava\u002Frich-domain-model","04.java\u002F04.rich-domain-model",{"title":2387,"path":2388,"stem":2389},"Патерни для складної бізнес-логіки","\u002Fjava\u002Fbusiness-logic-patterns","04.java\u002F05.business-logic-patterns",{"title":2391,"path":2392,"stem":2393},"Обробка помилок та валідація","\u002Fjava\u002Ferror-handling-validation","04.java\u002F06.error-handling-validation",{"title":2395,"path":2396,"stem":2397,"children":2398,"page":59},"Проектування баз даних","\u002Fjava\u002Fpr2","04.java\u002Fpr2",[2399,2403,2407,2411,2415,2419,2423,2427,2431,2435,2439,2443,2447,2451,2455,2459,2463,2467,2471,2475,2479,2483,2487,2491,2495,2499,2503,2507,2511,2515,2519,2523,2527,2531,2535,2539,2543],{"title":2400,"path":2401,"stem":2402},"Концептуальне моделювання: Мистецтво розуміння предметної області","\u002Fjava\u002Fpr2\u002Fconceptual-modeling","04.java\u002Fpr2\u002F01.conceptual-modeling",{"title":2404,"path":2405,"stem":2406},"Логічне моделювання: Від бізнес-ідей до структур даних","\u002Fjava\u002Fpr2\u002Flogical-modeling","04.java\u002Fpr2\u002F02.logical-modeling",{"title":2408,"path":2409,"stem":2410},"Нормалізація: Гігієна даних та боротьба з аномаліями","\u002Fjava\u002Fpr2\u002Fnormalization","04.java\u002Fpr2\u002F03.normalization",{"title":2412,"path":2413,"stem":2414},"Фізична схема: Від абстракції до DDL","\u002Fjava\u002Fpr2\u002Fphysical-schema","04.java\u002Fpr2\u002F04.physical-schema",{"title":2416,"path":2417,"stem":2418},"Архітектурна класифікація таблиць","\u002Fjava\u002Fpr2\u002Ftable-classification","04.java\u002Fpr2\u002F05.table-classification",{"title":2420,"path":2421,"stem":2422},"Database Migrations: Версіонування схеми з Flyway","\u002Fjava\u002Fpr2\u002Fdatabase-migrations","04.java\u002Fpr2\u002F06.database-migrations",{"title":2424,"path":2425,"stem":2426},"А що, якби це була не реляційна БД?","\u002Fjava\u002Fpr2\u002Fbeyond-relational","04.java\u002Fpr2\u002F07.beyond-relational",{"title":2428,"path":2429,"stem":2430},"Object-Relational Impedance Mismatch: Два світи, що не хочуть дружити","\u002Fjava\u002Fpr2\u002Fimpedance-mismatch","04.java\u002Fpr2\u002F09.impedance-mismatch",{"title":2432,"path":2433,"stem":2434},"JDBC: Перший контакт із базою даних","\u002Fjava\u002Fpr2\u002Fjdbc-fundamentals","04.java\u002Fpr2\u002F10.jdbc-fundamentals",{"title":2436,"path":2437,"stem":2438},"Якість коду: Spotless, SpotBugs та SonarQube","\u002Fjava\u002Fpr2\u002F10a.code-quality","04.java\u002Fpr2\u002F10a.code-quality",{"title":2440,"path":2441,"stem":2442},"Connection Pool: Патерн Object Pool для JDBC-з'єднань","\u002Fjava\u002Fpr2\u002Fconnection-pool","04.java\u002Fpr2\u002F11.connection-pool",{"title":2444,"path":2445,"stem":2446},"Row Data Gateway: Об'єкт як обгортка рядка таблиці","\u002Fjava\u002Fpr2\u002Frow-data-gateway","04.java\u002Fpr2\u002F12.row-data-gateway",{"title":2448,"path":2449,"stem":2450},"Table Data Gateway: Фасад таблиці як архітектурний відступ","\u002Fjava\u002Fpr2\u002Ftable-data-gateway","04.java\u002Fpr2\u002F13.table-data-gateway",{"title":2452,"path":2453,"stem":2454},"Repository + Data Mapper: Правильна шарова архітектура з JDBC","\u002Fjava\u002Fpr2\u002Frepository-data-mapper","04.java\u002Fpr2\u002F14.repository-data-mapper",{"title":2456,"path":2457,"stem":2458},"Identity Map: Кешування сутностей у рамках сесії","\u002Fjava\u002Fpr2\u002Fidentity-map","04.java\u002Fpr2\u002F15.identity-map",{"title":2460,"path":2461,"stem":2462},"Unit of Work: Відстеження змін і координація JDBC-транзакцій","\u002Fjava\u002Fpr2\u002Funit-of-work","04.java\u002Fpr2\u002F16.unit-of-work",{"title":2464,"path":2465,"stem":2466},"Strategy: Замінювані SQL-стратегії для підтримки різних СУБД","\u002Fjava\u002Fpr2\u002Fstrategy-sql","04.java\u002Fpr2\u002F17.strategy-sql",{"title":2468,"path":2469,"stem":2470},"Proxy: Lazy Loading для One-To-Many колекцій","\u002Fjava\u002Fpr2\u002Fproxy-lazy-loading","04.java\u002Fpr2\u002F18.proxy-lazy-loading",{"title":2472,"path":2473,"stem":2474},"Generic Repository через Java Reflection: анотації та динамічний SQL","\u002Fjava\u002Fpr2\u002Fgeneric-repository-reflection","04.java\u002Fpr2\u002F19.generic-repository-reflection",{"title":2476,"path":2477,"stem":2478},"Specification Pattern: Композиція бізнес-правил для складних запитів","\u002Fjava\u002Fpr2\u002Fspecification-pattern","04.java\u002Fpr2\u002F20.specification-pattern",{"title":2480,"path":2481,"stem":2482},"Розширені можливості Specification Pattern: підзапити, агрегації та гібридний підхід","\u002Fjava\u002Fpr2\u002F20a.advanced-specifications","04.java\u002Fpr2\u002F20a.advanced-specifications",{"title":2484,"path":2485,"stem":2486},"Асинхронність у JDBC: Від блокуючих викликів до CompletableFuture","\u002Fjava\u002Fpr2\u002Fasynchronous-jdbc","04.java\u002Fpr2\u002F21.asynchronous-jdbc",{"title":2488,"path":2489,"stem":2490},"Інтеграційне тестування JDBC-репозиторіїв: Embedded H2 та патерн AAA","\u002Fjava\u002Fpr2\u002Fintegration-testing-h2","04.java\u002Fpr2\u002F22.integration-testing-h2",{"title":2492,"path":2493,"stem":2494},"Testcontainers: Тестування з реальною PostgreSQL у Docker-контейнерах","\u002Fjava\u002Fpr2\u002Fintegration-testing-testcontainers","04.java\u002Fpr2\u002F23.integration-testing-testcontainers",{"title":2496,"path":2497,"stem":2498},"Google Guice: Впровадження залежностей у JavaFX-проєкті","\u002Fjava\u002Fpr2\u002Fdependency-injection-guice","04.java\u002Fpr2\u002F24.dependency-injection-guice",{"title":2500,"path":2501,"stem":2502},"JavaFX: Основи побудови графічних інтерфейсів","\u002Fjava\u002Fpr2\u002Fjavafx-fundamentals","04.java\u002Fpr2\u002F25.javafx-fundamentals",{"title":2504,"path":2505,"stem":2506},"Properties та Bindings: Реактивність у JavaFX","\u002Fjava\u002Fpr2\u002Fjavafx-properties-bindings","04.java\u002Fpr2\u002F26.javafx-properties-bindings",{"title":2508,"path":2509,"stem":2510},"MVC vs MVP vs MVVM: Еволюція архітектурних патернів UI","\u002Fjava\u002Fpr2\u002Fui-architecture-patterns","04.java\u002Fpr2\u002F27.ui-architecture-patterns",{"title":2512,"path":2513,"stem":2514},"MVVM на практиці: Побудова ViewModel","\u002Fjava\u002Fpr2\u002Fmvvm-viewmodel-implementation","04.java\u002Fpr2\u002F28.mvvm-viewmodel-implementation",{"title":2516,"path":2517,"stem":2518},"View та Controller: Зв'язування з ViewModel через FXML","\u002Fjava\u002Fpr2\u002Fmvvm-view-controller","04.java\u002Fpr2\u002F29.mvvm-view-controller",{"title":2520,"path":2521,"stem":2522},"Інтеграція MVVM з Guice: Автоматична ін'єкція залежностей","\u002Fjava\u002Fpr2\u002Fmvvm-guice-integration","04.java\u002Fpr2\u002F30.mvvm-guice-integration",{"title":2524,"path":2525,"stem":2526},"Валідація та обробка помилок у MVVM","\u002Fjava\u002Fpr2\u002Fmvvm-validation-error-handling","04.java\u002Fpr2\u002F31.mvvm-validation-error-handling",{"title":2528,"path":2529,"stem":2530},"Навігація та управління екранами у JavaFX MVVM","\u002Fjava\u002Fpr2\u002Fmvvm-navigation-screen-management","04.java\u002Fpr2\u002F32.mvvm-navigation-screen-management",{"title":2532,"path":2533,"stem":2534},"Тестування JavaFX MVVM-додатків","\u002Fjava\u002Fpr2\u002Fmvvm-testing","04.java\u002Fpr2\u002F33.mvvm-testing",{"title":2536,"path":2537,"stem":2538},"Стилізація та теми у JavaFX: CSS та User Experience","\u002Fjava\u002Fpr2\u002Fjavafx-styling-themes","04.java\u002Fpr2\u002F34.javafx-styling-themes",{"title":2540,"path":2541,"stem":2542},"AtlantaFX: Сучасні теми для JavaFX додатків","\u002Fjava\u002Fpr2\u002Fatlantafx-modern-themes","04.java\u002Fpr2\u002F35.atlantafx-modern-themes",{"title":2544,"path":2545,"stem":2546},"Пакування та розповсюдження JavaFX-додатків","\u002Fjava\u002Fpr2\u002Fjar-packaging-distribution","04.java\u002Fpr2\u002F36.jar-packaging-distribution",{"title":2548,"icon":2549,"path":2550,"stem":2551,"children":2552,"page":59},"Python","i-devicon-python","\u002Fpython","05.python",[2553,2557,2560,2564,2568,2572,2576,2580,2584,2588,2592,2596,2600,2604,2608,2669],{"title":2554,"path":2555,"stem":2556},"Модулі, Пакети та Віртуальні Середовища","\u002Fpython\u002Fmodules-packages-venv","05.python\u002F00.modules-packages-venv",{"title":71,"path":2558,"stem":2559},"\u002Fpython\u002Fclasses-objects","05.python\u002F01.classes-objects",{"title":2561,"path":2562,"stem":2563},"Інкапсуляція, Керування Доступом та Властивості","\u002Fpython\u002Fencapsulation","05.python\u002F02.encapsulation",{"title":2565,"path":2566,"stem":2567},"Наслідування, MRO та суперсила super()","\u002Fpython\u002Finheritance-mro","05.python\u002F03.inheritance-mro",{"title":2569,"path":2570,"stem":2571},"Абстракція — ABC проти Статичних Протоколів (PEP 544)","\u002Fpython\u002Fabstraction-protocols","05.python\u002F04.abstraction-protocols",{"title":2573,"path":2574,"stem":2575},"Магічні методи (Dunder) та Емуляція протоколів","\u002Fpython\u002Fdunder-methods","05.python\u002F05.dunder-methods",{"title":2577,"path":2578,"stem":2579},"Декоратори та Керування життєвим циклом методів","\u002Fpython\u002Fdecorators-static-class","05.python\u002F06.decorators-static-class",{"title":2581,"path":2582,"stem":2583},"Дескриптори — Магія доступу до атрибутів","\u002Fpython\u002Fdescriptors","05.python\u002F07.descriptors",{"title":2585,"path":2586,"stem":2587},"Метакласи — Динамічне створення класів під капотом CPython","\u002Fpython\u002Fmetaclasses","05.python\u002F08.metaclasses",{"title":2589,"path":2590,"stem":2591},"Dataclasses, NamedTuple та сучасні контейнери Python","\u002Fpython\u002Fmodern-containers","05.python\u002F09.modern-containers",{"title":2593,"path":2594,"stem":2595},"GIL та модель конкурентності CPython — фундамент перед потоками і процесами","\u002Fpython\u002Fgil-concurrency-intro","05.python\u002F11.gil-concurrency-intro",{"title":2597,"path":2598,"stem":2599},"Threading — конкурентність для I\u002FO-bound задач","\u002Fpython\u002Fthreading","05.python\u002F12.threading",{"title":2601,"path":2602,"stem":2603},"Multiprocessing — справжній паралелізм для CPU-bound задач","\u002Fpython\u002Fmultiprocessing","05.python\u002F13.multiprocessing",{"title":2605,"path":2606,"stem":2607},"asyncio — кооперативна конкурентність та event loop","\u002Fpython\u002Fasyncio","05.python\u002F14.asyncio",{"title":2609,"icon":92,"path":2610,"stem":2611,"children":2612,"page":59},"FastAPI","\u002Fpython\u002Ffastapi","05.python\u002Ffastapi",[2613,2617,2621,2625,2629,2633,2637,2641,2645,2649,2653,2657,2661,2665],{"title":2614,"path":2615,"stem":2616},"Глибокий Typing та Pydantic v2 — від анотацій до валідації","\u002Fpython\u002Ffastapi\u002Ftyping-pydantic","05.python\u002Ffastapi\u002F15.typing-pydantic",{"title":2618,"path":2619,"stem":2620},"WSGI, ASGI та Python Web-екосистема","\u002Fpython\u002Ffastapi\u002Fwsgi-asgi-ecosystem","05.python\u002Ffastapi\u002F16.wsgi-asgi-ecosystem",{"title":2622,"path":2623,"stem":2624},"FastAPI: Перший додаток, Uvicorn та OpenAPI","\u002Fpython\u002Ffastapi\u002Ffastapi-intro","05.python\u002Ffastapi\u002F17.fastapi-intro",{"title":2626,"path":2627,"stem":2628},"Маршрутизація, параметри запитів та APIRouter","\u002Fpython\u002Ffastapi\u002Ffastapi-routing-params","05.python\u002Ffastapi\u002F18.fastapi-routing-params",{"title":2630,"path":2631,"stem":2632},"Pydantic v2 у FastAPI — схеми, валідація та серіалізація","\u002Fpython\u002Ffastapi\u002Ffastapi-pydantic-schemas","05.python\u002Ffastapi\u002F19.fastapi-pydantic-schemas",{"title":2634,"path":2635,"stem":2636},"Dependency Injection — серце архітектури FastAPI","\u002Fpython\u002Ffastapi\u002Ffastapi-dependency-injection","05.python\u002Ffastapi\u002F20.fastapi-dependency-injection",{"title":2638,"path":2639,"stem":2640},"Обробка помилок, Middleware та CORS у FastAPI","\u002Fpython\u002Ffastapi\u002Ffastapi-errors-middleware","05.python\u002Ffastapi\u002F21.fastapi-errors-middleware",{"title":2642,"path":2643,"stem":2644},"SQLAlchemy 2.0 — ORM, Core та Async Engine","\u002Fpython\u002Ffastapi\u002Fsqlalchemy-orm","05.python\u002Ffastapi\u002F22.sqlalchemy-orm",{"title":2646,"path":2647,"stem":2648},"Alembic — міграції бази даних","\u002Fpython\u002Ffastapi\u002Falembic-migrations","05.python\u002Ffastapi\u002F23.alembic-migrations",{"title":2650,"path":2651,"stem":2652},"Repository Pattern та Clean Architecture у FastAPI","\u002Fpython\u002Ffastapi\u002Ffastapi-repository-clean-arch","05.python\u002Ffastapi\u002F24.fastapi-repository-clean-arch",{"title":2654,"path":2655,"stem":2656},"Автентифікація та авторизація — JWT, OAuth2, RBAC","\u002Fpython\u002Ffastapi\u002Ffastapi-auth-security","05.python\u002Ffastapi\u002F25.fastapi-auth-security",{"title":2658,"path":2659,"stem":2660},"Тестування FastAPI — pytest, httpx, fixtures","\u002Fpython\u002Ffastapi\u002Ffastapi-testing","05.python\u002Ffastapi\u002F26.fastapi-testing",{"title":2662,"path":2663,"stem":2664},"Async на повну — Background Tasks, WebSockets, SSE та Celery","\u002Fpython\u002Ffastapi\u002Ffastapi-async-advanced","05.python\u002Ffastapi\u002F27.fastapi-async-advanced",{"title":2666,"path":2667,"stem":2668},"Deployment — Docker, CI\u002FCD, Monitoring","\u002Fpython\u002Ffastapi\u002Ffastapi-deployment","05.python\u002Ffastapi\u002F28.fastapi-deployment",{"title":2670,"path":2671,"stem":2672},"[object Object]","\u002Fpython\u002Foop-plan","05.python\u002Foop-plan",{"title":2674,"icon":2675,"path":2676,"stem":2677,"children":2678,"page":59},"Бази даних","i-lucide-database","\u002Fdatabases","06.databases",[2679,2709,2732,2769,2798,2816,2850,2862,2871],{"title":2680,"icon":2681,"path":2682,"stem":2683,"children":2684,"page":59},"Intro","i-lucide-play","\u002Fdatabases\u002Fintro","06.databases\u002F01.intro",[2685,2689,2693,2697,2701,2705],{"title":2686,"path":2687,"stem":2688},"Введення в теорію баз даних","\u002Fdatabases\u002Fintro\u002Fintroduction-to-databases","06.databases\u002F01.intro\u002F01.introduction-to-databases",{"title":2690,"path":2691,"stem":2692},"Реляційна модель даних","\u002Fdatabases\u002Fintro\u002Frelational-model-theory","06.databases\u002F01.intro\u002F02.relational-model-theory",{"title":2694,"path":2695,"stem":2696},"ER-моделювання","\u002Fdatabases\u002Fintro\u002Fer-modeling","06.databases\u002F01.intro\u002F03.er-modeling",{"title":2698,"path":2699,"stem":2700},"Логічне проектування БД","\u002Fdatabases\u002Fintro\u002Flogical-schema","06.databases\u002F01.intro\u002F04.logical-schema",{"title":2702,"path":2703,"stem":2704},"Класифікація таблиць","\u002Fdatabases\u002Fintro\u002Ftable-classification","06.databases\u002F01.intro\u002F05.table-classification",{"title":2706,"path":2707,"stem":2708},"PlantUML для баз даних","\u002Fdatabases\u002Fintro\u002Fplantuml-diagrams","06.databases\u002F01.intro\u002F06.plantuml-diagrams",{"title":2710,"icon":2675,"path":2711,"stem":2712,"children":2713,"page":59},"MS SQL Server Start","\u002Fdatabases\u002Fms-sql-server-start","06.databases\u002F02.ms-sql-server-start",[2714,2718,2724,2728],{"title":2715,"path":2716,"stem":2717},"Типи даних у MS SQL Server","\u002Fdatabases\u002Fms-sql-server-start\u002Fdata-types","06.databases\u002F02.ms-sql-server-start\u002F01.data-types",{"title":2719,"path":2720,"stem":2721,"children":2722},"Індекси у MS SQL Server","\u002Fdatabases\u002Fms-sql-server-start\u002Fsql-indexes","06.databases\u002F02.ms-sql-server-start\u002F02.sql-indexes",[2723],{"title":2719,"path":2720,"stem":2721},{"title":2725,"path":2726,"stem":2727},"Системні бази даних MS SQL Server","\u002Fdatabases\u002Fms-sql-server-start\u002Fsystem-databases","06.databases\u002F02.ms-sql-server-start\u002F03.system-databases",{"title":2729,"path":2730,"stem":2731},"Огляд мови SQL та запитів","\u002Fdatabases\u002Fms-sql-server-start\u002Fsql-queries-overview","06.databases\u002F02.ms-sql-server-start\u002F04.sql-queries-overview",{"title":2733,"icon":2675,"path":2734,"stem":2735,"children":2736,"page":59},"SQL","\u002Fdatabases\u002Fsql","06.databases\u002F03.sql",[2737,2741,2745,2749,2753,2757,2761,2765],{"title":2738,"path":2739,"stem":2740},"Налаштування демонстраційної бази даних","\u002Fdatabases\u002Fsql\u002Fsample-database-setup","06.databases\u002F03.sql\u002F00.sample-database-setup",{"title":2742,"path":2743,"stem":2744},"DDL - Створення таблиць (CREATE TABLE)","\u002Fdatabases\u002Fsql\u002Fddl-create-table","06.databases\u002F03.sql\u002F01.ddl-create-table",{"title":2746,"path":2747,"stem":2748},"DDL - Зміна та видалення таблиць (ALTER, DROP)","\u002Fdatabases\u002Fsql\u002Fddl-alter-drop-table","06.databases\u002F03.sql\u002F02.ddl-alter-drop-table",{"title":2750,"path":2751,"stem":2752},"SELECT запити - Основи","\u002Fdatabases\u002Fsql\u002Fselect-queries-fundamentals","06.databases\u002F03.sql\u002F03.select-queries-fundamentals",{"title":2754,"path":2755,"stem":2756},"SELECT запити - Розширені можливості","\u002Fdatabases\u002Fsql\u002Fselect-queries-advanced","06.databases\u002F03.sql\u002F04.select-queries-advanced",{"title":2758,"path":2759,"stem":2760},"INSERT запити - Додавання даних","\u002Fdatabases\u002Fsql\u002Finsert-queries","06.databases\u002F03.sql\u002F05.insert-queries",{"title":2762,"path":2763,"stem":2764},"UPDATE та DELETE запити","\u002Fdatabases\u002Fsql\u002Fupdate-delete-queries","06.databases\u002F03.sql\u002F06.update-delete-queries",{"title":2766,"path":2767,"stem":2768},"Транзакції в SQL","\u002Fdatabases\u002Fsql\u002Ftransactions","06.databases\u002F03.sql\u002F07.transactions",{"title":2770,"icon":2675,"path":2771,"stem":2772,"children":2773,"page":59},"Multi Table Databases","\u002Fdatabases\u002Fmulti-table-databases","06.databases\u002F04.multi-table-databases",[2774,2778,2782,2786,2790,2794],{"title":2775,"path":2776,"stem":2777},"Зв'язки та нормалізація БД","\u002Fdatabases\u002Fmulti-table-databases\u002Frelationships-and-normalization","06.databases\u002F04.multi-table-databases\u002F00.relationships-and-normalization",{"title":2779,"path":2780,"stem":2781},"INNER JOIN - З'єднання таблиць","\u002Fdatabases\u002Fmulti-table-databases\u002Finner-join","06.databases\u002F04.multi-table-databases\u002F01.inner-join",{"title":2783,"path":2784,"stem":2785},"OUTER JOINs - LEFT, RIGHT, FULL","\u002Fdatabases\u002Fmulti-table-databases\u002Fouter-joins","06.databases\u002F04.multi-table-databases\u002F02.outer-joins",{"title":2787,"path":2788,"stem":2789},"CROSS та SELF JOINs","\u002Fdatabases\u002Fmulti-table-databases\u002Fcross-self-joins","06.databases\u002F04.multi-table-databases\u002F03.cross-self-joins",{"title":2791,"path":2792,"stem":2793},"Підзапити (Subqueries)","\u002Fdatabases\u002Fmulti-table-databases\u002Fsubqueries","06.databases\u002F04.multi-table-databases\u002F04.subqueries",{"title":2795,"path":2796,"stem":2797},"Агрегації з JOIN","\u002Fdatabases\u002Fmulti-table-databases\u002Faggregations-with-joins","06.databases\u002F04.multi-table-databases\u002F05.aggregations-with-joins",{"title":2799,"icon":2800,"path":2801,"stem":2802,"children":2803,"page":59},"Aggregate Functions","i-lucide-calculator","\u002Fdatabases\u002Faggregate-functions","06.databases\u002F05.aggregate-functions",[2804,2808,2812],{"title":2805,"path":2806,"stem":2807},"Функції агрегування в MS SQL Server","\u002Fdatabases\u002Faggregate-functions\u002Fintroduction-aggregate-functions","06.databases\u002F05.aggregate-functions\u002F01.introduction-aggregate-functions",{"title":2809,"path":2810,"stem":2811},"Групування даних в MS SQL Server","\u002Fdatabases\u002Faggregate-functions\u002Fgrouping-data","06.databases\u002F05.aggregate-functions\u002F02.grouping-data",{"title":2813,"path":2814,"stem":2815},"Підзапити з агрегатними функціями","\u002Fdatabases\u002Faggregate-functions\u002Fsubqueries-aggregates","06.databases\u002F05.aggregate-functions\u002F03.subqueries-aggregates",{"title":2817,"icon":2818,"path":2819,"stem":2820,"children":2821,"page":59},"Тригери та зберігаємі процедури","i-lucide-database-zap","\u002Fdatabases\u002Ftriggers-stored-procedures","06.databases\u002F07.triggers-stored-procedures",[2822,2826,2830,2834,2838,2842,2846],{"title":2823,"path":2824,"stem":2825},"DML-тригери","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fdml-triggers","06.databases\u002F07.triggers-stored-procedures\u002F01.dml-triggers",{"title":2827,"path":2828,"stem":2829},"DDL-тригери","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fddl-triggers","06.databases\u002F07.triggers-stored-procedures\u002F02.ddl-triggers",{"title":2831,"path":2832,"stem":2833},"Transact-SQL розширення","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Ftransact-sql-extensions","06.databases\u002F07.triggers-stored-procedures\u002F03.transact-sql-extensions",{"title":2835,"path":2836,"stem":2837},"Транзакції","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Ftransactions","06.databases\u002F07.triggers-stored-procedures\u002F04.transactions",{"title":2839,"path":2840,"stem":2841},"Зберігаємі процедури","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fstored-procedures","06.databases\u002F07.triggers-stored-procedures\u002F05.stored-procedures",{"title":2843,"path":2844,"stem":2845},"Користувацькі функції","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fuser-defined-functions","06.databases\u002F07.triggers-stored-procedures\u002F06.user-defined-functions",{"title":2847,"path":2848,"stem":2849},"Безпека баз даних","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fsecurity","06.databases\u002F07.triggers-stored-procedures\u002F08.security",{"title":2847,"icon":793,"path":2851,"stem":2852,"children":2853,"page":59},"\u002Fdatabases\u002Fsecurity","06.databases\u002F08.security",[2854,2858],{"title":2855,"path":2856,"stem":2857},"Вступ до безпеки баз даних","\u002Fdatabases\u002Fsecurity\u002Fintroduction","06.databases\u002F08.security\u002F01.introduction",{"title":2859,"path":2860,"stem":2861},"Системні представлення та метадані","\u002Fdatabases\u002Fsecurity\u002Fsystem-views","06.databases\u002F08.security\u002F02.system-views",{"title":2863,"icon":2864,"path":2865,"stem":2866,"children":2867,"page":59},"Резервне копіювання та відновлення","i-lucide-database-backup","\u002Fdatabases\u002Fbackup-recovery","06.databases\u002F09.backup-recovery",[2868],{"title":2863,"path":2869,"stem":2870},"\u002Fdatabases\u002Fbackup-recovery\u002Fbackup-restore","06.databases\u002F09.backup-recovery\u002F01.backup-restore",{"title":2872,"icon":2873,"path":2874,"stem":2875,"children":2876,"page":59},"Повнотекстовий пошук","i-lucide-search","\u002Fdatabases\u002Ffull-text-search","06.databases\u002F10.full-text-search",[2877],{"title":2872,"path":2878,"stem":2879},"\u002Fdatabases\u002Ffull-text-search\u002Ffull-text-search","06.databases\u002F10.full-text-search\u002F01.full-text-search",{"title":2881,"icon":2882,"path":2883,"stem":2884,"children":2885,"page":59},"Tools","i-lucide-wrench","\u002Ftools","07.tools",[2886,2962],{"title":2887,"icon":2888,"path":2889,"stem":2890,"children":2891},"Docker","i-simple-icons-docker","\u002Ftools\u002Fdocker","07.tools\u002F01.docker\u002Findex",[2892,2894,2898,2902,2906,2910,2914,2918,2922,2926,2930,2934,2938,2942,2946,2950,2954,2958],{"title":2893,"path":2889,"stem":2890},"Docker: від нуля до production",{"title":2895,"path":2896,"stem":2897},"Контейнеризація — від проблеми до рішення","\u002Ftools\u002Fdocker\u002Fcontainerization-concept","07.tools\u002F01.docker\u002F01.containerization-concept",{"title":2899,"path":2900,"stem":2901},"Docker — що це і навіщо?","\u002Ftools\u002Fdocker\u002Fdocker-what-and-why","07.tools\u002F01.docker\u002F02.docker-what-and-why",{"title":2903,"path":2904,"stem":2905},"Архітектура Docker Engine","\u002Ftools\u002Fdocker\u002Fdocker-architecture","07.tools\u002F01.docker\u002F03.docker-architecture",{"title":2907,"path":2908,"stem":2909},"Встановлення Docker","\u002Ftools\u002Fdocker\u002Finstallation","07.tools\u002F01.docker\u002F04.installation",{"title":2911,"path":2912,"stem":2913},"Перший контейнер — docker run","\u002Ftools\u002Fdocker\u002Ffirst-container","07.tools\u002F01.docker\u002F05.first-container",{"title":2915,"path":2916,"stem":2917},"Життєвий цикл контейнера","\u002Ftools\u002Fdocker\u002Fcontainer-lifecycle","07.tools\u002F01.docker\u002F06.container-lifecycle",{"title":2919,"path":2920,"stem":2921},"Docker Images — фундаментальні концепції","\u002Ftools\u002Fdocker\u002Fdocker-images-fundamentals","07.tools\u002F01.docker\u002F07.docker-images-fundamentals",{"title":2923,"path":2924,"stem":2925},"Dockerfile — основи","\u002Ftools\u002Fdocker\u002Fdockerfile-basics","07.tools\u002F01.docker\u002F08.dockerfile-basics",{"title":2927,"path":2928,"stem":2929},"Dockerfile — просунуті техніки","\u002Ftools\u002Fdocker\u002Fdockerfile-advanced","07.tools\u002F01.docker\u002F09.dockerfile-advanced",{"title":2931,"path":2932,"stem":2933},"Build Context та кешування шарів","\u002Ftools\u002Fdocker\u002Fbuild-context-and-cache","07.tools\u002F01.docker\u002F10.build-context-and-cache",{"title":2935,"path":2936,"stem":2937},"Реєстри Docker-образів","\u002Ftools\u002Fdocker\u002Fimage-registries","07.tools\u002F01.docker\u002F11.image-registries",{"title":2939,"path":2940,"stem":2941},"Контейнеризація .NET додатків","\u002Ftools\u002Fdocker\u002Fdotnet-containerization","07.tools\u002F01.docker\u002F12.dotnet-containerization",{"title":2943,"path":2944,"stem":2945},"Томи та збереження даних","\u002Ftools\u002Fdocker\u002Fvolumes-and-data","07.tools\u002F01.docker\u002F13.volumes-and-data",{"title":2947,"path":2948,"stem":2949},"Основи мережі в Docker","\u002Ftools\u002Fdocker\u002Fnetworking-basics","07.tools\u002F01.docker\u002F14.networking-basics",{"title":2951,"path":2952,"stem":2953},"Змінні оточення та конфігурація","\u002Ftools\u002Fdocker\u002Fenvironment-and-configuration","07.tools\u002F01.docker\u002F15.environment-and-configuration",{"title":2955,"path":2956,"stem":2957},"Docker Compose — оркестрація контейнерів","\u002Ftools\u002Fdocker\u002Fdocker-compose-basics","07.tools\u002F01.docker\u002F16.docker-compose-basics",{"title":2959,"path":2960,"stem":2961},"Docker Compose — Multi-Service застосунки","\u002Ftools\u002Fdocker\u002Fcompose-multi-service","07.tools\u002F01.docker\u002F17.compose-multi-service",{"title":2963,"icon":2964,"path":2965,"stem":2966,"children":2967},"Kubernetes","simple-icons:kubernetes","\u002Ftools\u002Fkubernetes","07.tools\u002F02.kubernetes\u002Findex",[2968,2970,2974,2978,2982,2986,2990,2994,2998],{"title":2969,"path":2965,"stem":2966},"Kubernetes: від розробки до production",{"title":2971,"path":2972,"stem":2973},"Kubernetes — коли Docker Compose більше не вистачає","\u002Ftools\u002Fkubernetes\u002Fwhy-kubernetes","07.tools\u002F02.kubernetes\u002F01.why-kubernetes",{"title":2975,"path":2976,"stem":2977},"Архітектура Kubernetes — анатомія кластера","\u002Ftools\u002Fkubernetes\u002Fkubernetes-architecture","07.tools\u002F02.kubernetes\u002F02.kubernetes-architecture",{"title":2979,"path":2980,"stem":2981},"Локальне середовище — minikube, kind та k3s","\u002Ftools\u002Fkubernetes\u002Flocal-environment","07.tools\u002F02.kubernetes\u002F03.local-environment",{"title":2983,"path":2984,"stem":2985},"Pod — атомарна одиниця Kubernetes","\u002Ftools\u002Fkubernetes\u002Fpods-and-containers","07.tools\u002F02.kubernetes\u002F04.pods-and-containers",{"title":2987,"path":2988,"stem":2989},"Патерни використання Pod","\u002Ftools\u002Fkubernetes\u002Fpod-patterns","07.tools\u002F02.kubernetes\u002F05.pod-patterns",{"title":2991,"path":2992,"stem":2993},"Deployment — декларативне управління Pod","\u002Ftools\u002Fkubernetes\u002Fdeployment-basics","07.tools\u002F02.kubernetes\u002F06.deployment-basics",{"title":2995,"path":2996,"stem":2997},"Rolling Updates та управління життєвим циклом Deployment","\u002Ftools\u002Fkubernetes\u002Fdeployment-rolling-updates","07.tools\u002F02.kubernetes\u002F07.deployment-rolling-updates",{"title":2999,"path":3000,"stem":3001},"Service — мережева абстракція для Pod","\u002Ftools\u002Fkubernetes\u002Fservices-networking","07.tools\u002F02.kubernetes\u002F08.services-networking",{"title":3003,"icon":3004,"path":3005,"stem":3006,"children":3007,"page":59},"Software Engineering","i-lucide-code-2","\u002Fsoftware-engineering","09.software-engineering",[3008,3012,3016,3020,3024,3028,3032,3036,3040,3044,3048],{"title":3009,"path":3010,"stem":3011},"1. Аналіз предметної області. Експертні знання та складність","\u002Fsoftware-engineering\u002Fintro-subdomains","09.software-engineering\u002F01.intro-subdomains",{"title":3013,"path":3014,"stem":3015},"2. Обмежені контексти. Інтеграція обмежених контекстів","\u002Fsoftware-engineering\u002Fintegrating-limited-contexts","09.software-engineering\u002F02.integrating-limited-contexts",{"title":3017,"path":3018,"stem":3019},"3. Реалізація простої бізнес-логіки","\u002Fsoftware-engineering\u002Fsimple","09.software-engineering\u002F03.simple",{"title":3021,"path":3022,"stem":3023},"4. Опрацювання складної бізнес-логіки","\u002Fsoftware-engineering\u002Fcomplex-business-logic","09.software-engineering\u002F04.complex-business-logic",{"title":3025,"path":3026,"stem":3027},"5. Моделювання фактора часу. Подієво-орієнтована архітектура.","\u002Fsoftware-engineering\u002Fmodelling-the-time-factor","09.software-engineering\u002F05.modelling-the-time-factor",{"title":3029,"path":3030,"stem":3031},"6. Архітектурні патерни","\u002Fsoftware-engineering\u002Farchitectural-patterns","09.software-engineering\u002F06.architectural-patterns",{"title":3033,"path":3034,"stem":3035},"Паттерни взаємодії","\u002Fsoftware-engineering\u002Fpatterns-of-interaction","09.software-engineering\u002F07.patterns-of-interaction",{"title":3037,"path":3038,"stem":3039},"Евристика проєктування","\u002Fsoftware-engineering\u002Fdesign-heuristics","09.software-engineering\u002F08.design-heuristics",{"title":3041,"path":3042,"stem":3043},"Еволюція проєктних рішень","\u002Fsoftware-engineering\u002Fevolution-of-design-solutions","09.software-engineering\u002F09.evolution-of-design-solutions",{"title":3045,"path":3046,"stem":3047},"EventStorming","\u002Fsoftware-engineering\u002Feventstorming","09.software-engineering\u002F10.eventstorming",{"title":3049,"path":3050,"stem":3051},"DDD на практиці","\u002Fsoftware-engineering\u002Fddd-in-practice","09.software-engineering\u002F11.ddd-in-practice",{"title":3053,"icon":943,"path":3054,"stem":3055,"children":3056,"page":59},"DDD","\u002Fddd","10.ddd",[3057,3061,3065,3069,3073,3077,3081,3085,3089,3093,3097,3101,3105],{"title":3058,"path":3059,"stem":3060},"Аналіз предметної області","\u002Fddd\u002Fdomain-analysis","10.ddd\u002F01.domain-analysis",{"title":3062,"path":3063,"stem":3064},"Експертні знання про предметну область","\u002Fddd\u002Fdomain-expert-knowledge","10.ddd\u002F02.domain-expert-knowledge",{"title":3066,"path":3067,"stem":3068},"Як осмислити складність предметної області","\u002Fddd\u002Fmanaging-domain-complexity","10.ddd\u002F03.managing-domain-complexity",{"title":3070,"path":3071,"stem":3072},"Інтеграція обмежених контекстів","\u002Fddd\u002Fbounded-context-integration","10.ddd\u002F04.bounded-context-integration",{"title":3074,"path":3075,"stem":3076},"Реалізація простої бізнес-логіки","\u002Fddd\u002Fsimple-business-logic","10.ddd\u002F05.simple-business-logic",{"title":3078,"path":3079,"stem":3080},"Обробка складної бізнес-логіки","\u002Fddd\u002Fcomplex-business-logic","10.ddd\u002F06.complex-business-logic",{"title":3082,"path":3083,"stem":3084},"Моделювання фактора часу","\u002Fddd\u002Ftime-modeling","10.ddd\u002F07.time-modeling",{"title":3086,"path":3087,"stem":3088},"Глава 8. Архітектурні Патерни","\u002Fddd\u002Farchitectural-patterns","10.ddd\u002F08.architectural-patterns",{"title":3090,"path":3091,"stem":3092},"Глава 9. Патерни Взаємодії","\u002Fddd\u002Finteraction-patterns","10.ddd\u002F09.interaction-patterns",{"title":3094,"path":3095,"stem":3096},"Глава 10. Проектні Евристики","\u002Fddd\u002Fdesign-heuristics","10.ddd\u002F10.design-heuristics",{"title":3098,"path":3099,"stem":3100},"Глава 11. Еволюція Проектних Рішень","\u002Fddd\u002Fevolution-of-design-decisions","10.ddd\u002F11.evolution-of-design-decisions",{"title":3102,"path":3103,"stem":3104},"Глава 12. EventStorming","\u002Fddd\u002Fevent-storming","10.ddd\u002F12.event-storming",{"title":3106,"path":3107,"stem":3108},"Глава 13. DDD на Практиці","\u002Fddd\u002Fddd-in-practice","10.ddd\u002F13.ddd-in-practice",{"title":3110,"icon":3111,"path":3112,"stem":3113,"children":3114,"page":59},"Media Streaming","i-lucide-video","\u002Fmedia-streaming","11.media-streaming",[3115,3119,3123,3127,3131,3135,3139],{"title":3116,"path":3117,"stem":3118},"01. Магія Стрімінгу: Що відбувається, коли ви натискаєте \"Play\"","\u002Fmedia-streaming\u002Fintroduction","11.media-streaming\u002F01.introduction",{"title":3120,"path":3121,"stem":3122},"02. Анатомія Медіа: Кодеки, Контейнери та Стиснення","\u002Fmedia-streaming\u002Faudio-video-anatomy","11.media-streaming\u002F02.audio-video-anatomy",{"title":3124,"path":3125,"stem":3126},"03. The Gym: FFmpeg Deep Dive","\u002Fmedia-streaming\u002Fffmpeg-gym","11.media-streaming\u002F03.ffmpeg-gym",{"title":3128,"path":3129,"stem":3130},"04. HLS Protocol: HTTP Live Streaming у Деталях","\u002Fmedia-streaming\u002Fhls-protocol","11.media-streaming\u002F04.hls-protocol",{"title":3132,"path":3133,"stem":3134},"05. DASH Protocol: Відкритий Стандарт","\u002Fmedia-streaming\u002Fdash-protocol","11.media-streaming\u002F05.dash-protocol",{"title":3136,"path":3137,"stem":3138},"06. Масштабування: CDN та Adaptive Bitrate","\u002Fmedia-streaming\u002Fcdn-and-adaptive-bitrate","11.media-streaming\u002F06.cdn-and-adaptive-bitrate",{"title":3140,"path":3141,"stem":3142},"07. Війна із Затримкою (Latency)","\u002Fmedia-streaming\u002Frealtime-latency","11.media-streaming\u002F07.realtime-latency",{"title":3144,"icon":3145,"path":3146,"stem":3147,"children":3148,"page":59},"HTML & CSS","i-devicon-html5","\u002Fhtml-css","12.html-css",[3149,3153,3157,3161,3165,3169,3173,3177,3181,3185,3189,3193,3197,3201,3205,3209,3213,3217,3221,3225,3229,3233,3237,3241,3245,3249,3253,3257,3261,3265],{"title":3150,"path":3151,"stem":3152},"Вступ до HTML. Структура документа","\u002Fhtml-css\u002Fintro-html-structure","12.html-css\u002F01.intro-html-structure",{"title":3154,"path":3155,"stem":3156},"Форматування тексту в HTML","\u002Fhtml-css\u002Fhtml-text-formatting","12.html-css\u002F02.html-text-formatting",{"title":3158,"path":3159,"stem":3160},"Посилання та зображення в HTML","\u002Fhtml-css\u002Fhtml-links-images","12.html-css\u002F03.html-links-images",{"title":3162,"path":3163,"stem":3164},"Списки та таблиці в HTML","\u002Fhtml-css\u002Fhtml-lists-tables","12.html-css\u002F04.html-lists-tables",{"title":3166,"path":3167,"stem":3168},"Форми в HTML","\u002Fhtml-css\u002Fhtml-forms","12.html-css\u002F05.html-forms",{"title":3170,"path":3171,"stem":3172},"Семантичні елементи HTML5","\u002Fhtml-css\u002Fhtml-semantic-elements","12.html-css\u002F06.html-semantic-elements",{"title":3174,"path":3175,"stem":3176},"Мультимедіа та розширені елементи HTML","\u002Fhtml-css\u002Fhtml-multimedia-advanced","12.html-css\u002F07.html-multimedia-advanced",{"title":3178,"path":3179,"stem":3180},"Мікророзмітка та SEO в HTML","\u002Fhtml-css\u002Fhtml-microdata-seo","12.html-css\u002F08.html-microdata-seo",{"title":3182,"path":3183,"stem":3184},"Вступ до CSS. Селектори та специфічність","\u002Fhtml-css\u002Fcss-intro-selectors","12.html-css\u002F09.css-intro-selectors",{"title":3186,"path":3187,"stem":3188},"Блокова модель CSS. Відступи. Box Sizing","\u002Fhtml-css\u002Fcss-box-model","12.html-css\u002F10.css-box-model",{"title":3190,"path":3191,"stem":3192},"Розміри у CSS: повний довідник одиниць і ключових слів","\u002Fhtml-css\u002F10a.css-sizing","12.html-css\u002F10a.css-sizing",{"title":3194,"path":3195,"stem":3196},"Типографіка в CSS. Шрифти та текст","\u002Fhtml-css\u002Fcss-typography","12.html-css\u002F11.css-typography",{"title":3198,"path":3199,"stem":3200},"Кольори та фони в CSS","\u002Fhtml-css\u002Fcss-colors-backgrounds","12.html-css\u002F12.css-colors-backgrounds",{"title":3202,"path":3203,"stem":3204},"Тіні та фільтри в CSS","\u002Fhtml-css\u002F12b.css-shadows-filters","12.html-css\u002F12b.css-shadows-filters",{"title":3206,"path":3207,"stem":3208},"CSS Flexbox: Фундамент гнучких макетів","\u002Fhtml-css\u002Fcss-flexbox-fundamentals","12.html-css\u002F13.css-flexbox-fundamentals",{"title":3210,"path":3211,"stem":3212},"CSS Flexbox: Вирівнювання та Позиціонування","\u002Fhtml-css\u002Fcss-flexbox-alignment-sizing-and-patterns","12.html-css\u002F14.css-flexbox-alignment-sizing-and-patterns",{"title":3214,"path":3215,"stem":3216},"CSS Grid. Двовимірний макет. Частина 1","\u002Fhtml-css\u002Fcss-layout-grid","12.html-css\u002F15.css-layout-grid",{"title":3218,"path":3219,"stem":3220},"CSS Grid. Двовимірний макет. Частина 2","\u002Fhtml-css\u002Fcss-layout-grid-advanced","12.html-css\u002F16.css-layout-grid-advanced",{"title":3222,"path":3223,"stem":3224},"Позиціонування в CSS. Z-index. Stacking Context","\u002Fhtml-css\u002Fcss-positioning","12.html-css\u002F17.css-positioning",{"title":3226,"path":3227,"stem":3228},"CSS Анімації та Переходи","\u002Fhtml-css\u002Fcss-animations-transitions","12.html-css\u002F18.css-animations-transitions",{"title":3230,"path":3231,"stem":3232},"Адаптивний дизайн. Media Queries. Частина 1","\u002Fhtml-css\u002Fcss-responsive-media-queries","12.html-css\u002F19.css-responsive-media-queries",{"title":3234,"path":3235,"stem":3236},"Адаптивний дизайн. Частина 2: clamp(), Container Queries, @layer","\u002Fhtml-css\u002Fcss-responsive-advanced","12.html-css\u002F20.css-responsive-advanced",{"title":3238,"path":3239,"stem":3240},"CSS Custom Properties. Методології. Сучасний CSS","\u002Fhtml-css\u002Fcss-variables-methodologies","12.html-css\u002F21.css-variables-methodologies",{"title":3242,"path":3243,"stem":3244},"Сучасний CSS 2023–2025: Нові можливості","\u002Fhtml-css\u002Fcss-modern-features","12.html-css\u002F22.css-modern-features",{"title":3246,"path":3247,"stem":3248},"CSS Nesting, @layer, @scope та @property: нативний препроцесор","\u002Fhtml-css\u002F22a.css-nesting-modern-syntax","12.html-css\u002F22a.css-nesting-modern-syntax",{"title":3250,"path":3251,"stem":3252},"CSS для форм та інтерактивних станів","\u002Fhtml-css\u002Fcss-forms-interactive-states","12.html-css\u002F23.css-forms-interactive-states",{"title":3254,"path":3255,"stem":3256},"Доступність у CSS (CSS Accessibility)","\u002Fhtml-css\u002Fcss-accessibility","12.html-css\u002F24.css-accessibility",{"title":3258,"path":3259,"stem":3260},"CSS-функції та сучасні sizing primitives","\u002Fhtml-css\u002Fcss-functions-sizing","12.html-css\u002F25.css-functions-sizing",{"title":3262,"path":3263,"stem":3264},"Rendering Pipeline і CSS Performance","\u002Fhtml-css\u002Fcss-rendering-performance","12.html-css\u002F26.css-rendering-performance",{"title":3266,"path":3267,"stem":3268},"CSS Best Practices: типові ситуації та правильні рішення","\u002Fhtml-css\u002Fcss-best-practices","12.html-css\u002F27.css-best-practices",{"title":3270,"path":3271,"stem":3272,"children":3273,"page":59},"AWS","\u002Faws","13.aws",[3274,3278,3282,3286,3290,3294,3298,3302,3306,3310,3314,3318,3322,3326,3330,3334,3338,3342],{"title":3275,"path":3276,"stem":3277},"Реєстрація AWS акаунту та студентські програми","\u002Faws\u002Faccount-registration","13.aws\u002F00.account-registration",{"title":3279,"path":3280,"stem":3281},"Вступ до хмарних обчислень та AWS","\u002Faws\u002Fintroduction-to-cloud","13.aws\u002F01.introduction-to-cloud",{"title":3283,"path":3284,"stem":3285},"AWS IAM — Identity and Access Management","\u002Faws\u002Fiam","13.aws\u002F02.iam",{"title":3287,"path":3288,"stem":3289},"AWS IAM CLI — Довідник команд","\u002Faws\u002F02a.iam-doc","13.aws\u002F02a.iam-doc",{"title":3291,"path":3292,"stem":3293},"Docker та контейнеризація в AWS — ECR, ECS та Fargate","\u002Faws\u002Fdocker-ecs","13.aws\u002F03.docker-ecs",{"title":3295,"path":3296,"stem":3297},"AWS ECR \u002F ECS CLI — Довідник команд","\u002Faws\u002F03a.docker-ecs-doc","13.aws\u002F03a.docker-ecs-doc",{"title":3299,"path":3300,"stem":3301},"Amazon EC2 — Elastic Compute Cloud","\u002Faws\u002Fec2","13.aws\u002F04.ec2",{"title":3303,"path":3304,"stem":3305},"AWS EC2 CLI — Довідник команд","\u002Faws\u002F04a.ec2-doc","13.aws\u002F04a.ec2-doc",{"title":3307,"path":3308,"stem":3309},"Elastic Load Balancing та Auto Scaling","\u002Faws\u002Falb-asg","13.aws\u002F05.alb-asg",{"title":3311,"path":3312,"stem":3313},"Amazon S3 — Simple Storage Service","\u002Faws\u002Fs3","13.aws\u002F06.s3",{"title":3315,"path":3316,"stem":3317},"Amazon CloudFront — Content Delivery Network","\u002Faws\u002Fcloudfront","13.aws\u002F07.cloudfront",{"title":3319,"path":3320,"stem":3321},"Amazon RDS — Relational Database Service","\u002Faws\u002Frds","13.aws\u002F08.rds",{"title":3323,"path":3324,"stem":3325},"Amazon DynamoDB — NoSQL Database","\u002Faws\u002Fdynamodb","13.aws\u002F09.dynamodb",{"title":3327,"path":3328,"stem":3329},"AWS Lambda та Serverless Compute","\u002Faws\u002Flambda","13.aws\u002F10.lambda",{"title":3331,"path":3332,"stem":3333},"Amazon Bedrock - Foundation Models, RAG та Agents","\u002Faws\u002Fbedrock","13.aws\u002F22.bedrock",{"title":3335,"path":3336,"stem":3337},"Amazon Rekognition - Комп'ютерний зір","\u002Faws\u002Frekognition","13.aws\u002F23.rekognition",{"title":3339,"path":3340,"stem":3341},"Amazon Textract - Інтелектуальний аналіз документів","\u002Faws\u002Ftextract","13.aws\u002F24.textract",{"title":3343,"path":3344,"stem":3345},"Amazon Polly, Transcribe, Comprehend та Translate","\u002Faws\u002Faudio-nlp-services","13.aws\u002F25.audio-nlp-services",{"title":3347,"path":3348,"stem":3349,"children":3350,"page":59},"Ai Development","\u002Fai-development","14.ai-development",[3351],{"title":3352,"path":3353,"stem":3354,"children":3355,"page":59},"Foundations","\u002Fai-development\u002Ffoundations","14.ai-development\u002F00.foundations",[3356],{"title":3357,"path":3358,"stem":3359},"Модуль 0.1. Що таке Large Language Model (LLM)","\u002Fai-development\u002Ffoundations\u002Fwhat-is-llm","14.ai-development\u002F00.foundations\u002F01.what-is-llm",{"title":3361,"path":3362,"stem":3363,"children":3364,"page":59},"React Native","\u002Freact-native","15.react-native",[3365,3386],{"title":3366,"path":3367,"stem":3368,"children":3369,"page":59},"Version1","\u002Freact-native\u002Fversion1","15.react-native\u002Fversion1",[3370,3374,3378,3382],{"title":3371,"path":3372,"stem":3373},"Що таке React Native","\u002Freact-native\u002Fversion1\u002Fwhat-is-react-native","15.react-native\u002Fversion1\u002F01.what-is-react-native",{"title":3375,"path":3376,"stem":3377},"Як влаштований React Native «під капотом»","\u002Freact-native\u002Fversion1\u002Freact-native-architecture","15.react-native\u002Fversion1\u002F02.react-native-architecture",{"title":3379,"path":3380,"stem":3381},"Від React до React Native: ключові відмінності","\u002Freact-native\u002Fversion1\u002Freact-native-vs-react","15.react-native\u002Fversion1\u002F03.react-native-vs-react",{"title":3383,"path":3384,"stem":3385},"View та Text — фундаментальні будівельні блоки","\u002Freact-native\u002Fversion1\u002Fview-and-text","15.react-native\u002Fversion1\u002F04.view-and-text",{"title":3387,"path":3388,"stem":3389,"children":3390,"page":59},"Version2","\u002Freact-native\u002Fversion2","15.react-native\u002Fversion2",[3391,3395,3399,3403,3407,3411,3415,3419,3423,3427,3431,3435,3439,3443,3447,3451,3455,3459,3463,3467,3471,3475,3479,3483,3487,3491],{"title":3392,"path":3393,"stem":3394},"React Native — навіщо він потрібен","\u002Freact-native\u002Fversion2\u002Fwhy-react-native","15.react-native\u002Fversion2\u002F01.why-react-native",{"title":3396,"path":3397,"stem":3398},"Налаштування середовища розробки","\u002Freact-native\u002Fversion2\u002Fenvironment-setup","15.react-native\u002Fversion2\u002F02.environment-setup",{"title":3400,"path":3401,"stem":3402},"Expo і класичний React Native — два шляхи одного фреймворку","\u002Freact-native\u002Fversion2\u002Fexpo-vs-cli-landscape","15.react-native\u002Fversion2\u002F03.expo-vs-cli-landscape",{"title":3404,"path":3405,"stem":3406},"Середовище Expo — перший запуск","\u002Freact-native\u002Fversion2\u002Fexpo-setup-and-tooling","15.react-native\u002Fversion2\u002F04.expo-setup-and-tooling",{"title":3408,"path":3409,"stem":3410},"Структура проєкту та перші UI-примітиви","\u002Freact-native\u002Fversion2\u002Fproject-structure-and-conventions","15.react-native\u002Fversion2\u002F05.project-structure-and-conventions",{"title":3412,"path":3413,"stem":3414},"Базові компоненти React Native","\u002Freact-native\u002Fversion2\u002Fcore-components","15.react-native\u002Fversion2\u002F06.core-components",{"title":3416,"path":3417,"stem":3418},"Flexbox і layout у React Native","\u002Freact-native\u002Fversion2\u002Fflexbox-and-layout","15.react-native\u002Fversion2\u002F07.flexbox-and-layout",{"title":3420,"path":3421,"stem":3422},"StyleSheet і теми (light \u002F dark)","\u002Freact-native\u002Fversion2\u002Fstylesheet-and-theming","15.react-native\u002Fversion2\u002F08.stylesheet-and-theming",{"title":3424,"path":3425,"stem":3426},"Списки та віртуалізація","\u002Freact-native\u002Fversion2\u002Flists-and-virtualization","15.react-native\u002Fversion2\u002F09.lists-and-virtualization",{"title":3428,"path":3429,"stem":3430},"Форми, ввід і валідація","\u002Freact-native\u002Fversion2\u002Fforms-input-validation","15.react-native\u002Fversion2\u002F10.forms-input-validation",{"title":3432,"path":3433,"stem":3434},"Основи Expo Router","\u002Freact-native\u002Fversion2\u002Fexpo-router-basics","15.react-native\u002Fversion2\u002F11.expo-router-basics",{"title":3436,"path":3437,"stem":3438},"Вкладені навігатори та модалки","\u002Freact-native\u002Fversion2\u002Fnested-navigators-and-modals","15.react-native\u002Fversion2\u002F12.nested-navigators-and-modals",{"title":3440,"path":3441,"stem":3442},"Deep linking і параметри маршрутів","\u002Freact-native\u002Fversion2\u002Fdeep-linking-and-params","15.react-native\u002Fversion2\u002F13.deep-linking-and-params",{"title":3444,"path":3445,"stem":3446},"Робота з мережею та життєвий цикл застосунку","\u002Freact-native\u002Fversion2\u002Fnetworking-and-app-lifecycle","15.react-native\u002Fversion2\u002F14.networking-and-app-lifecycle",{"title":3448,"path":3449,"stem":3450},"Redux Toolkit на мобільних платформах","\u002Freact-native\u002Fversion2\u002Fredux-toolkit-on-mobile","15.react-native\u002Fversion2\u002F15.redux-toolkit-on-mobile",{"title":3452,"path":3453,"stem":3454},"RTK Query на мобільних платформах","\u002Freact-native\u002Fversion2\u002Frtk-query-mobile","15.react-native\u002Fversion2\u002F16.rtk-query-mobile",{"title":3456,"path":3457,"stem":3458},"Автентифікація та Безпечне Зберігання","\u002Freact-native\u002Fversion2\u002Fauth-secure-storage","15.react-native\u002Fversion2\u002F18.auth-secure-storage",{"title":3460,"path":3461,"stem":3462},"Локальне сховище — AsyncStorage, MMKV, SQLite","\u002Freact-native\u002Fversion2\u002Flocal-storage-mmkv-sqlite","15.react-native\u002Fversion2\u002F19.local-storage-mmkv-sqlite",{"title":3464,"path":3465,"stem":3466},"Офлайн-First і синхронізація","\u002Freact-native\u002Fversion2\u002Foffline-first-sync","15.react-native\u002Fversion2\u002F20.offline-first-sync",{"title":3468,"path":3469,"stem":3470},"Камера, медіа та файлова система","\u002Freact-native\u002Fversion2\u002Fcamera-media-filesystem","15.react-native\u002Fversion2\u002F21.camera-media-filesystem",{"title":3472,"path":3473,"stem":3474},"Карти та геолокація","\u002Freact-native\u002Fversion2\u002Fmaps-and-location","15.react-native\u002Fversion2\u002F22.maps-and-location",{"title":3476,"path":3477,"stem":3478},"Жести та дотики","\u002Freact-native\u002Fversion2\u002Fgestures-and-touch","15.react-native\u002Fversion2\u002F23.gestures-and-touch",{"title":3480,"path":3481,"stem":3482},"Анімації з Reanimated","\u002Freact-native\u002Fversion2\u002Freanimated-animations","15.react-native\u002Fversion2\u002F24.reanimated-animations",{"title":3484,"path":3485,"stem":3486},"Push і локальні сповіщення","\u002Freact-native\u002Fversion2\u002Fpush-and-local-notifications","15.react-native\u002Fversion2\u002F25.push-and-local-notifications",{"title":3488,"path":3489,"stem":3490},"Доступність та інтернаціоналізація","\u002Freact-native\u002Fversion2\u002Faccessibility-and-i18n","15.react-native\u002Fversion2\u002F26.accessibility-and-i18n",{"title":3492,"path":3493,"stem":3494},"EAS Build та профілі збірки","\u002Freact-native\u002Fversion2\u002Feas-build-and-profiles","15.react-native\u002Fversion2\u002F29.eas-build-and-profiles",{"title":3496,"path":3497,"stem":3498,"children":3499,"page":59},"Ai Python","\u002Fai-python","16.ai-python",[3500,3504,3508],{"title":3501,"path":3502,"stem":3503},"Вступ до штучного інтелекту та машинного навчання","\u002Fai-python\u002Fintro-to-ai","16.ai-python\u002F01.intro-to-ai",{"title":3505,"path":3506,"stem":3507},"Знайомство з Jupyter Notebook та JupyterLab","\u002Fai-python\u002Fjupyter-notebook","16.ai-python\u002F02.jupyter-notebook",{"title":3509,"path":3510,"stem":3511},"Робота з даними з використанням NumPy і pandas","\u002Fai-python\u002Fnumpy-pandas","16.ai-python\u002F03.numpy-pandas",{"title":3513,"icon":658,"path":3514,"stem":3515,"children":3516,"page":59},"Клієнт-серверна архітектура","\u002Fclient-server-architecture","17.client-server-architecture",[3517,3521],{"title":3518,"path":3519,"stem":3520},"Архітектура клієнт-серверних систем та основи Go","\u002Fclient-server-architecture\u002Fclient-server-architecture-and-go","17.client-server-architecture\u002F01.client-server-architecture-and-go",{"title":3522,"path":3523,"stem":3524},"Система типів та модель пам’яті мови Go","\u002Fclient-server-architecture\u002Ftype-system-and-memory-model","17.client-server-architecture\u002F02.type-system-and-memory-model",{"title":3526,"icon":1946,"path":3527,"stem":3528,"children":3529,"page":59},"Розробка WEB-застосувань","\u002Fweb-development","18.web-development",[3530,3575,3613,3642],{"title":3531,"icon":658,"path":3532,"stem":3533,"children":3534,"page":59},"Архітектура комп'ютерних мереж та мережеві протоколи","\u002Fweb-development\u002Fnetwork-architecture-and-protocols","18.web-development\u002F01.network-architecture-and-protocols",[3535,3539,3543,3547,3551,3555,3559,3563,3567,3571],{"title":3536,"path":3537,"stem":3538},"Еволюція веброзробки та модель клієнт-сервер","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fweb-evolution-client-server","18.web-development\u002F01.network-architecture-and-protocols\u002F01.web-evolution-client-server",{"title":3540,"path":3541,"stem":3542},"Еталонна модель OSI","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fosi-model","18.web-development\u002F01.network-architecture-and-protocols\u002F02.osi-model",{"title":3544,"path":3545,"stem":3546},"Стек протоколів TCP\u002FIP","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Ftcp-ip-stack","18.web-development\u002F01.network-architecture-and-protocols\u002F03.tcp-ip-stack",{"title":3548,"path":3549,"stem":3550},"IP-адресація, порти та сокети","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fip-addressing-ports-sockets","18.web-development\u002F01.network-architecture-and-protocols\u002F04.ip-addressing-ports-sockets",{"title":3552,"path":3553,"stem":3554},"Протоколи TCP та UDP","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Ftcp-udp-protocols","18.web-development\u002F01.network-architecture-and-protocols\u002F05.tcp-udp-protocols",{"title":3556,"path":3557,"stem":3558},"Система доменних імен DNS","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fdns-system","18.web-development\u002F01.network-architecture-and-protocols\u002F06.dns-system",{"title":3560,"path":3561,"stem":3562},"Протокол SMTP та поштові протоколи","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fsmtp-email-protocols","18.web-development\u002F01.network-architecture-and-protocols\u002F07.smtp-email-protocols",{"title":3564,"path":3565,"stem":3566},"Протокол WebSocket","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fwebsocket-protocol","18.web-development\u002F01.network-architecture-and-protocols\u002F08.websocket-protocol",{"title":3568,"path":3569,"stem":3570},"Протокол SSH","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fssh-protocol","18.web-development\u002F01.network-architecture-and-protocols\u002F09.ssh-protocol",{"title":3572,"path":3573,"stem":3574},"Огляд сучасних серверних технологій","\u002Fweb-development\u002Fnetwork-architecture-and-protocols\u002Fmodern-backend-technologies","18.web-development\u002F01.network-architecture-and-protocols\u002F10.modern-backend-technologies",{"title":3576,"icon":3577,"path":3578,"stem":3579,"children":3580,"page":59},"Протокол HTTP та захищена передача даних HTTPS","i-lucide-lock","\u002Fweb-development\u002Fhttp-and-https","18.web-development\u002F02.http-and-https",[3581,3585,3589,3593,3597,3601,3605,3609],{"title":3582,"path":3583,"stem":3584},"Вступ до протоколу HTTP та еволюція веб-технологій","\u002Fweb-development\u002Fhttp-and-https\u002Fintroduction-and-evolution","18.web-development\u002F02.http-and-https\u002F01.introduction-and-evolution",{"title":3586,"path":3587,"stem":3588},"Анатомія HTTP-запиту","\u002Fweb-development\u002Fhttp-and-https\u002Fhttp-request-structure","18.web-development\u002F02.http-and-https\u002F02.http-request-structure",{"title":3590,"path":3591,"stem":3592},"Анатомія HTTP-відповіді","\u002Fweb-development\u002Fhttp-and-https\u002Fhttp-response-structure","18.web-development\u002F02.http-and-https\u002F03.http-response-structure",{"title":3594,"path":3595,"stem":3596},"Методи HTTP та їхня семантика","\u002Fweb-development\u002Fhttp-and-https\u002Fhttp-methods","18.web-development\u002F02.http-and-https\u002F04.http-methods",{"title":3598,"path":3599,"stem":3600},"Коди статусу HTTP та їхнє призначення","\u002Fweb-development\u002Fhttp-and-https\u002Fhttp-status-codes","18.web-development\u002F02.http-and-https\u002F05.http-status-codes",{"title":3602,"path":3603,"stem":3604},"HTTP-заголовки та їхнє призначення","\u002Fweb-development\u002Fhttp-and-https\u002Fhttp-headers","18.web-development\u002F02.http-and-https\u002F06.http-headers",{"title":3606,"path":3607,"stem":3608},"CORS та механізми безпеки HTTP","\u002Fweb-development\u002Fhttp-and-https\u002Fcors-and-security","18.web-development\u002F02.http-and-https\u002F07.cors-and-security",{"title":3610,"path":3611,"stem":3612},"HTTPS та криптографічні основи TLS","\u002Fweb-development\u002Fhttp-and-https\u002Fhttps-and-tls","18.web-development\u002F02.http-and-https\u002F08.https-and-tls",{"title":3614,"icon":2326,"path":3615,"stem":3616,"children":3617,"page":59},"Система типів мови TypeScript","\u002Fweb-development\u002Ftypescript-type-system","18.web-development\u002F03.typescript-type-system",[3618,3622,3626,3630,3634,3638],{"title":3619,"path":3620,"stem":3621},"Знайомство з TypeScript Compiler","\u002Fweb-development\u002Ftypescript-type-system\u002Fintroduction-compiler-config","18.web-development\u002F03.typescript-type-system\u002F01.introduction-compiler-config",{"title":3623,"path":3624,"stem":3625},"Примітивні типи даних: string, number, boolean","\u002Fweb-development\u002Ftypescript-type-system\u002Fprimitive-special-types","18.web-development\u002F03.typescript-type-system\u002F02.primitive-special-types",{"title":3627,"path":3628,"stem":3629},"Масиви, кортежі та об","\u002Fweb-development\u002Ftypescript-type-system\u002Farrays-tuples-objects","18.web-development\u002F03.typescript-type-system\u002F03.arrays-tuples-objects",{"title":3631,"path":3632,"stem":3633},"Union типи, Intersection типи та літеральні типи","\u002Fweb-development\u002Ftypescript-type-system\u002Funion-intersection-literals","18.web-development\u002F03.typescript-type-system\u002F04.union-intersection-literals",{"title":3635,"path":3636,"stem":3637},"Type Narrowing (звуження типів)","\u002Fweb-development\u002Ftypescript-type-system\u002Ftype-narrowing","18.web-development\u002F03.typescript-type-system\u002F05.type-narrowing",{"title":3639,"path":3640,"stem":3641},"Типізація функцій","\u002Fweb-development\u002Ftypescript-type-system\u002Ffunctions-typing","18.web-development\u002F03.typescript-type-system\u002F06.functions-typing",{"title":3643,"icon":2326,"path":3644,"stem":3645,"children":3646,"page":59},"Розширені засоби мови TypeScript","\u002Fweb-development\u002Ftypescript-advanced","18.web-development\u002F04.typescript-advanced",[3647,3651,3655,3659,3663,3667],{"title":3648,"path":3649,"stem":3650},"Interfaces та Classes","\u002Fweb-development\u002Ftypescript-advanced\u002Finterfaces-classes","18.web-development\u002F04.typescript-advanced\u002F01.interfaces-classes",{"title":3652,"path":3653,"stem":3654},"Основи Generic типів","\u002Fweb-development\u002Ftypescript-advanced\u002Fgenerics-fundamentals","18.web-development\u002F04.typescript-advanced\u002F02.generics-fundamentals",{"title":3656,"path":3657,"stem":3658},"Enums та Decorators","\u002Fweb-development\u002Ftypescript-advanced\u002Fenums-decorators","18.web-development\u002F04.typescript-advanced\u002F03.enums-decorators",{"title":3660,"path":3661,"stem":3662},"Utility Types","\u002Fweb-development\u002Ftypescript-advanced\u002Futility-types","18.web-development\u002F04.typescript-advanced\u002F04.utility-types",{"title":3664,"path":3665,"stem":3666},"Mapped та Conditional Types","\u002Fweb-development\u002Ftypescript-advanced\u002Fmapped-conditional-types","18.web-development\u002F04.typescript-advanced\u002F05.mapped-conditional-types",{"title":3668,"path":3669,"stem":3670},"Модулі та Strict Mode","\u002Fweb-development\u002Ftypescript-advanced\u002Fmodules-strict-mode","18.web-development\u002F04.typescript-advanced\u002F06.modules-strict-mode",{"title":3672,"path":3673,"stem":3674,"children":3675,"page":59},"Tailwind","\u002Ftailwind","21.tailwind",[3676,3680,3684,3688,3692,3696,3700,3704,3708,3712,3716,3720],{"title":3677,"path":3678,"stem":3679},"Що таке Tailwind CSS і навіщо він потрібен","\u002Ftailwind\u002Ftailwind-intro-philosophy","21.tailwind\u002F01.tailwind-intro-philosophy",{"title":3681,"path":3682,"stem":3683},"Встановлення та налаштування Tailwind CSS v4","\u002Ftailwind\u002Ftailwind-installation-setup","21.tailwind\u002F02.tailwind-installation-setup",{"title":3685,"path":3686,"stem":3687},"Utility-класи: основи та система Tailwind","\u002Ftailwind\u002Ftailwind-utility-classes-core","21.tailwind\u002F03.tailwind-utility-classes-core",{"title":3689,"path":3690,"stem":3691},"Layout: Flexbox та Grid через Tailwind","\u002Ftailwind\u002Ftailwind-flexbox-grid","21.tailwind\u002F04.tailwind-flexbox-grid",{"title":3693,"path":3694,"stem":3695},"Кастомізація теми через @theme у Tailwind v4","\u002Ftailwind\u002Ftailwind-theme-customization","21.tailwind\u002F05.tailwind-theme-customization",{"title":3697,"path":3698,"stem":3699},"Варіанти: hover, focus, responsive, dark mode та нові v4","\u002Ftailwind\u002Ftailwind-variants-states","21.tailwind\u002F06.tailwind-variants-states",{"title":3701,"path":3702,"stem":3703},"Типографіка та система кольорів у Tailwind v4","\u002Ftailwind\u002Ftailwind-typography-colors","21.tailwind\u002F07.tailwind-typography-colors",{"title":3705,"path":3706,"stem":3707},"Компоненти та повторюваність: @apply, @utility та патерни","\u002Ftailwind\u002Ftailwind-components-patterns","21.tailwind\u002F08.tailwind-components-patterns",{"title":3709,"path":3710,"stem":3711},"Темна тема та система дизайн-токенів у Tailwind v4","\u002Ftailwind\u002Ftailwind-dark-mode-theming","21.tailwind\u002F09.tailwind-dark-mode-theming",{"title":3713,"path":3714,"stem":3715},"Довільні значення та контейнерні запити у Tailwind v4","\u002Ftailwind\u002Ftailwind-arbitrary-container-queries","21.tailwind\u002F10.tailwind-arbitrary-container-queries",{"title":3717,"path":3718,"stem":3719},"Анімації, трансформації та 3D у Tailwind v4","\u002Ftailwind\u002Ftailwind-animations-transforms","21.tailwind\u002F11.tailwind-animations-transforms",{"title":3721,"path":3722,"stem":3723},"Tailwind CLI, PostCSS та інтеграція з фреймворками","\u002Ftailwind\u002Ftailwind-cli-tooling","21.tailwind\u002F12.tailwind-cli-tooling",{"title":3725,"path":3726,"stem":3727},"Тестування компонентів діаграм","\u002Ftest-components","98.test-components",{"id":3729,"title":3452,"body":3730,"description":35929,"extension":35930,"links":35931,"meta":35932,"navigation":3876,"path":3453,"seo":35933,"stem":3454,"__hash__":35934},"docs\u002F15.react-native\u002Fversion2\u002F16.rtk-query-mobile.md",{"type":3731,"value":3732,"toc":35804},"minimark",[3733,3737,3792,3795,3800,3808,3813,3821,4587,4590,5023,5029,5033,5036,5416,5422,5426,5429,5453,5456,5797,5801,5804,5824,5827,6073,6078,6082,6123,6127,6135,6510,6513,6738,6743,6794,6827,6829,6833,6836,6840,6851,6856,6859,7120,7398,7401,7609,7611,7613,7618,7659,7663,7674,7678,7824,7922,7924,8034,8036,8038,8043,8085,8089,8289,8293,8296,8568,8600,8604,8607,8776,9087,9089,9095,9098,9102,9105,9167,9177,9181,9184,9433,9438,9478,9482,9485,9716,9721,9817,9821,9824,10753,10758,10814,10820,10823,11004,11010,11013,11755,11760,12157,12159,12196,12277,12279,12281,12285,12288,12292,12301,12305,12308,12667,12671,12674,12970,12975,13013,13017,13020,13080,13087,13091,13097,13218,13223,13434,13438,13441,14119,14123,14281,14287,14293,14297,14300,14394,14403,14418,14422,14431,14434,14448,14451,15293,15297,15497,15507,15509,15513,15520,15524,15527,15711,15716,15884,15890,15894,15897,16035,16040,16234,16239,16281,16294,16298,16301,16765,16770,17170,17175,17249,17252,17268,17272,17275,17358,17366,17542,17552,17559,17875,17879,17882,18000,18010,18479,18484,19094,19098,19101,19125,19130,19481,19486,19500,19507,19510,19620,19625,19759,19769,19778,19780,19784,19799,19803,19879,19884,19898,19902,19905,20236,20240,20924,20929,21116,21120,21123,21161,21166,21245,21250,21684,21688,21691,21946,21950,22237,22241,22424,22429,22829,22833,23484,23488,23491,23751,23755,24125,24130,24144,24146,24150,24158,24162,24165,24296,24301,24304,24310,24315,24405,24412,24416,24422,24618,24623,24769,24776,24780,24783,25140,25145,25162,25175,25179,25182,25817,25822,26313,26317,26515,26519,26522,27133,27137,27231,27235,27238,27562,27566,27569,27803,27806,27828,27830,27834,27844,27858,28288,28290,28297,28302,28683,28685,28689,28702,29145,29147,29151,29154,29158,29189,29193,31052,31054,31058,31070,31077,31831,31835,32025,32032,32841,32843,32847,32888,32890,32894,32971,32973,32977,33021,33023,33027,33030,33034,33039,33048,33052,33498,33502,33738,33743,33780,33807,33809,33813,33816,34203,34207,34523,34527,34572,34574,34578,34581,34961,34965,35119,35123,35169,35171,35175,35273,35275,35278,35800],[3734,3735,3452],"h1",{"id":3736},"rtk-query-на-мобільних-платформах",[3738,3739,3740,3761],"card-group",{},[3741,3742,3745],"card",{"icon":3743,"title":3744},"i-lucide-target","🎯 Мета навчального матеріалу",[3746,3747,3748,3752,3755,3758],"ul",{},[3749,3750,3751],"li",{},"Зрозуміти різницю між клієнтським та серверним станом у мобільних застосунках",[3749,3753,3754],{},"Навчитися працювати з RTK Query від найпростіших запитів до складних сценаріїв",[3749,3756,3757],{},"Опанувати систему кешування та автоматичної інвалідації даних",[3749,3759,3760],{},"Створити повноцінний мобільний застосунок з серверною взаємодією",[3741,3762,3765],{"icon":3763,"title":3764},"i-lucide-key","🔑 Що ви дізнаєтесь",[3746,3766,3767,3774,3780,3786],{},[3749,3768,3769,3773],{},[3770,3771,3772],"strong",{},"Базові концепції:"," Query та Mutation ендпоінти, хуки для компонентів",[3749,3775,3776,3779],{},[3770,3777,3778],{},"Кешування:"," Автоматичне збереження даних, теги інвалідації",[3749,3781,3782,3785],{},[3770,3783,3784],{},"Мобільна специфіка:"," Робота з фокусом застосунку, відновлення мережі",[3749,3787,3788,3791],{},[3770,3789,3790],{},"Просунуті техніки:"," Оптимістичні оновлення, пагінація, WebSockets",[3793,3794],"hr",{},[3796,3797,3799],"h2",{"id":3798},"чому-потрібен-rtk-query-розбір-реальної-проблеми","Чому потрібен RTK Query? Розбір реальної проблеми",[3801,3802,3803,3804,3807],"p",{},"Уявіть, що ви розробляєте мобільний застосунок ",[3770,3805,3806],{},"Nomad"," для планування подорожей. У вас є екран зі списком поїздок, і ви вирішили використовувати Redux для керування станом. Давайте подивимось, з якими проблемами ви зіткнетеся при ручному підході.",[3809,3810,3812],"h3",{"id":3811},"проблема-1-завантаження-списку-поїздок-традиційний-підхід","Проблема 1: Завантаження списку поїздок (традиційний підхід)",[3801,3814,3815,3816,3820],{},"Спочатку створюємо слайс (",[3817,3818,3819],"em",{},"slice",") для зберігання поїздок:",[3822,3823,3828],"pre",{"className":3824,"code":3825,"language":3826,"meta":3827,"style":3827},"language-typescript shiki shiki-themes light-plus dark-plus dark-plus","\u002F\u002F src\u002Fstore\u002FtripsSlice.ts — ТРАДИЦІЙНИЙ ПІДХІД\nimport { createSlice, createAsyncThunk } from '@reduxjs\u002Ftoolkit'\n\n\u002F\u002F Визначаємо структуру даних поїздки\ninterface Trip {\n    id: string\n    title: string\n    region: string\n    startDate: string\n}\n\n\u002F\u002F Описуємо стан слайса з усіма необхідними полями\ninterface TripsState {\n    trips: Trip[]           \u002F\u002F Масив завантажених поїздок\n    isLoading: boolean      \u002F\u002F Чи відбувається зараз завантаження?\n    error: string | null    \u002F\u002F Текст помилки, якщо щось пішло не так\n}\n\n\u002F\u002F Початковий стан при запуску застосунку\nconst initialState: TripsState = {\n    trips: [],\n    isLoading: false,\n    error: null,\n}\n\n\u002F\u002F Створюємо асинхронну дію для завантаження даних з сервера\nexport const fetchTrips = createAsyncThunk(\n    'trips\u002FfetchTrips',\n    async () => {\n        const response = await fetch('http:\u002F\u002Flocalhost:3000\u002Ftrips')\n        if (!response.ok) {\n            throw new Error('Не вдалося завантажити поїздки')\n        }\n        return response.json()\n    }\n)\n\n\u002F\u002F Створюємо слайс з обробкою всіх можливих станів запиту\nconst tripsSlice = createSlice({\n    name: 'trips',\n    initialState,\n    reducers: {},\n    extraReducers: (builder) => {\n        builder\n            \u002F\u002F Запит почався — встановлюємо прапорець завантаження\n            .addCase(fetchTrips.pending, (state) => {\n                state.isLoading = true\n                state.error = null\n            })\n            \u002F\u002F Запит успішно завершився — зберігаємо дані\n            .addCase(fetchTrips.fulfilled, (state, action) => {\n                state.isLoading = false\n                state.trips = action.payload\n            })\n            \u002F\u002F Запит завершився помилкою — зберігаємо повідомлення\n            .addCase(fetchTrips.rejected, (state, action) => {\n                state.isLoading = false\n                state.error = action.error.message || 'Невідома помилка'\n            })\n    },\n})\n\nexport default tripsSlice.reducer\n","typescript","",[3829,3830,3831,3840,3871,3878,3884,3898,3910,3920,3930,3940,3946,3951,3957,3967,3984,3998,4018,4023,4028,4034,4052,4061,4073,4084,4089,4094,4100,4121,4129,4143,4169,4190,4209,4215,4231,4237,4242,4247,4253,4268,4279,4287,4296,4318,4324,4330,4361,4377,4392,4398,4404,4435,4449,4468,4473,4479,4509,4522,4550,4555,4561,4567,4572],"code",{"__ignoreMap":3827},[3832,3833,3836],"span",{"class":3834,"line":3835},"line",1,[3832,3837,3839],{"class":3838},"spJ8K","\u002F\u002F src\u002Fstore\u002FtripsSlice.ts — ТРАДИЦІЙНИЙ ПІДХІД\n",[3832,3841,3843,3847,3851,3855,3858,3861,3864,3867],{"class":3834,"line":3842},2,[3832,3844,3846],{"class":3845},"s8xlr","import",[3832,3848,3850],{"class":3849},"sHH4Y"," { ",[3832,3852,3854],{"class":3853},"siwwj","createSlice",[3832,3856,3857],{"class":3849},", ",[3832,3859,3860],{"class":3853},"createAsyncThunk",[3832,3862,3863],{"class":3849}," } ",[3832,3865,3866],{"class":3845},"from",[3832,3868,3870],{"class":3869},"sbdoH"," '@reduxjs\u002Ftoolkit'\n",[3832,3872,3874],{"class":3834,"line":3873},3,[3832,3875,3877],{"emptyLinePlaceholder":3876},true,"\n",[3832,3879,3881],{"class":3834,"line":3880},4,[3832,3882,3883],{"class":3838},"\u002F\u002F Визначаємо структуру даних поїздки\n",[3832,3885,3887,3891,3895],{"class":3834,"line":3886},5,[3832,3888,3890],{"class":3889},"su1O8","interface",[3832,3892,3894],{"class":3893},"sN1BT"," Trip",[3832,3896,3897],{"class":3849}," {\n",[3832,3899,3901,3904,3907],{"class":3834,"line":3900},6,[3832,3902,3903],{"class":3853},"    id",[3832,3905,3906],{"class":3849},": ",[3832,3908,3909],{"class":3893},"string\n",[3832,3911,3913,3916,3918],{"class":3834,"line":3912},7,[3832,3914,3915],{"class":3853},"    title",[3832,3917,3906],{"class":3849},[3832,3919,3909],{"class":3893},[3832,3921,3923,3926,3928],{"class":3834,"line":3922},8,[3832,3924,3925],{"class":3853},"    region",[3832,3927,3906],{"class":3849},[3832,3929,3909],{"class":3893},[3832,3931,3933,3936,3938],{"class":3834,"line":3932},9,[3832,3934,3935],{"class":3853},"    startDate",[3832,3937,3906],{"class":3849},[3832,3939,3909],{"class":3893},[3832,3941,3943],{"class":3834,"line":3942},10,[3832,3944,3945],{"class":3849},"}\n",[3832,3947,3949],{"class":3834,"line":3948},11,[3832,3950,3877],{"emptyLinePlaceholder":3876},[3832,3952,3954],{"class":3834,"line":3953},12,[3832,3955,3956],{"class":3838},"\u002F\u002F Описуємо стан слайса з усіма необхідними полями\n",[3832,3958,3960,3962,3965],{"class":3834,"line":3959},13,[3832,3961,3890],{"class":3889},[3832,3963,3964],{"class":3893}," TripsState",[3832,3966,3897],{"class":3849},[3832,3968,3970,3973,3975,3978,3981],{"class":3834,"line":3969},14,[3832,3971,3972],{"class":3853},"    trips",[3832,3974,3906],{"class":3849},[3832,3976,3977],{"class":3893},"Trip",[3832,3979,3980],{"class":3849},"[]           ",[3832,3982,3983],{"class":3838},"\u002F\u002F Масив завантажених поїздок\n",[3832,3985,3987,3990,3992,3995],{"class":3834,"line":3986},15,[3832,3988,3989],{"class":3853},"    isLoading",[3832,3991,3906],{"class":3849},[3832,3993,3994],{"class":3893},"boolean",[3832,3996,3997],{"class":3838},"      \u002F\u002F Чи відбувається зараз завантаження?\n",[3832,3999,4001,4004,4006,4009,4012,4015],{"class":3834,"line":4000},16,[3832,4002,4003],{"class":3853},"    error",[3832,4005,3906],{"class":3849},[3832,4007,4008],{"class":3893},"string",[3832,4010,4011],{"class":3849}," | ",[3832,4013,4014],{"class":3893},"null",[3832,4016,4017],{"class":3838},"    \u002F\u002F Текст помилки, якщо щось пішло не так\n",[3832,4019,4021],{"class":3834,"line":4020},17,[3832,4022,3945],{"class":3849},[3832,4024,4026],{"class":3834,"line":4025},18,[3832,4027,3877],{"emptyLinePlaceholder":3876},[3832,4029,4031],{"class":3834,"line":4030},19,[3832,4032,4033],{"class":3838},"\u002F\u002F Початковий стан при запуску застосунку\n",[3832,4035,4037,4040,4044,4046,4049],{"class":3834,"line":4036},20,[3832,4038,4039],{"class":3889},"const",[3832,4041,4043],{"class":4042},"s-QsJ"," initialState",[3832,4045,3906],{"class":3849},[3832,4047,4048],{"class":3893},"TripsState",[3832,4050,4051],{"class":3849}," = {\n",[3832,4053,4055,4058],{"class":3834,"line":4054},21,[3832,4056,4057],{"class":3853},"    trips:",[3832,4059,4060],{"class":3849}," [],\n",[3832,4062,4064,4067,4070],{"class":3834,"line":4063},22,[3832,4065,4066],{"class":3853},"    isLoading:",[3832,4068,4069],{"class":3889}," false",[3832,4071,4072],{"class":3849},",\n",[3832,4074,4076,4079,4082],{"class":3834,"line":4075},23,[3832,4077,4078],{"class":3853},"    error:",[3832,4080,4081],{"class":3889}," null",[3832,4083,4072],{"class":3849},[3832,4085,4087],{"class":3834,"line":4086},24,[3832,4088,3945],{"class":3849},[3832,4090,4092],{"class":3834,"line":4091},25,[3832,4093,3877],{"emptyLinePlaceholder":3876},[3832,4095,4097],{"class":3834,"line":4096},26,[3832,4098,4099],{"class":3838},"\u002F\u002F Створюємо асинхронну дію для завантаження даних з сервера\n",[3832,4101,4103,4106,4109,4112,4115,4118],{"class":3834,"line":4102},27,[3832,4104,4105],{"class":3845},"export",[3832,4107,4108],{"class":3889}," const",[3832,4110,4111],{"class":4042}," fetchTrips",[3832,4113,4114],{"class":3849}," = ",[3832,4116,3860],{"class":4117},"s8Opu",[3832,4119,4120],{"class":3849},"(\n",[3832,4122,4124,4127],{"class":3834,"line":4123},28,[3832,4125,4126],{"class":3869},"    'trips\u002FfetchTrips'",[3832,4128,4072],{"class":3849},[3832,4130,4132,4135,4138,4141],{"class":3834,"line":4131},29,[3832,4133,4134],{"class":3889},"    async",[3832,4136,4137],{"class":3849}," () ",[3832,4139,4140],{"class":3889},"=>",[3832,4142,3897],{"class":3849},[3832,4144,4146,4149,4152,4154,4157,4160,4163,4166],{"class":3834,"line":4145},30,[3832,4147,4148],{"class":3889},"        const",[3832,4150,4151],{"class":4042}," response",[3832,4153,4114],{"class":3849},[3832,4155,4156],{"class":3845},"await",[3832,4158,4159],{"class":4117}," fetch",[3832,4161,4162],{"class":3849},"(",[3832,4164,4165],{"class":3869},"'http:\u002F\u002Flocalhost:3000\u002Ftrips'",[3832,4167,4168],{"class":3849},")\n",[3832,4170,4172,4175,4178,4181,4184,4187],{"class":3834,"line":4171},31,[3832,4173,4174],{"class":3845},"        if",[3832,4176,4177],{"class":3849}," (!",[3832,4179,4180],{"class":3853},"response",[3832,4182,4183],{"class":3849},".",[3832,4185,4186],{"class":3853},"ok",[3832,4188,4189],{"class":3849},") {\n",[3832,4191,4193,4196,4199,4202,4204,4207],{"class":3834,"line":4192},32,[3832,4194,4195],{"class":3845},"            throw",[3832,4197,4198],{"class":3889}," new",[3832,4200,4201],{"class":4117}," Error",[3832,4203,4162],{"class":3849},[3832,4205,4206],{"class":3869},"'Не вдалося завантажити поїздки'",[3832,4208,4168],{"class":3849},[3832,4210,4212],{"class":3834,"line":4211},33,[3832,4213,4214],{"class":3849},"        }\n",[3832,4216,4218,4221,4223,4225,4228],{"class":3834,"line":4217},34,[3832,4219,4220],{"class":3845},"        return",[3832,4222,4151],{"class":3853},[3832,4224,4183],{"class":3849},[3832,4226,4227],{"class":4117},"json",[3832,4229,4230],{"class":3849},"()\n",[3832,4232,4234],{"class":3834,"line":4233},35,[3832,4235,4236],{"class":3849},"    }\n",[3832,4238,4240],{"class":3834,"line":4239},36,[3832,4241,4168],{"class":3849},[3832,4243,4245],{"class":3834,"line":4244},37,[3832,4246,3877],{"emptyLinePlaceholder":3876},[3832,4248,4250],{"class":3834,"line":4249},38,[3832,4251,4252],{"class":3838},"\u002F\u002F Створюємо слайс з обробкою всіх можливих станів запиту\n",[3832,4254,4256,4258,4261,4263,4265],{"class":3834,"line":4255},39,[3832,4257,4039],{"class":3889},[3832,4259,4260],{"class":4042}," tripsSlice",[3832,4262,4114],{"class":3849},[3832,4264,3854],{"class":4117},[3832,4266,4267],{"class":3849},"({\n",[3832,4269,4271,4274,4277],{"class":3834,"line":4270},40,[3832,4272,4273],{"class":3853},"    name:",[3832,4275,4276],{"class":3869}," 'trips'",[3832,4278,4072],{"class":3849},[3832,4280,4282,4285],{"class":3834,"line":4281},41,[3832,4283,4284],{"class":3853},"    initialState",[3832,4286,4072],{"class":3849},[3832,4288,4290,4293],{"class":3834,"line":4289},42,[3832,4291,4292],{"class":3853},"    reducers:",[3832,4294,4295],{"class":3849}," {},\n",[3832,4297,4299,4302,4305,4308,4311,4314,4316],{"class":3834,"line":4298},43,[3832,4300,4301],{"class":4117},"    extraReducers",[3832,4303,4304],{"class":3853},":",[3832,4306,4307],{"class":3849}," (",[3832,4309,4310],{"class":3853},"builder",[3832,4312,4313],{"class":3849},") ",[3832,4315,4140],{"class":3889},[3832,4317,3897],{"class":3849},[3832,4319,4321],{"class":3834,"line":4320},44,[3832,4322,4323],{"class":3853},"        builder\n",[3832,4325,4327],{"class":3834,"line":4326},45,[3832,4328,4329],{"class":3838},"            \u002F\u002F Запит почався — встановлюємо прапорець завантаження\n",[3832,4331,4333,4336,4339,4341,4344,4346,4349,4352,4355,4357,4359],{"class":3834,"line":4332},46,[3832,4334,4335],{"class":3849},"            .",[3832,4337,4338],{"class":4117},"addCase",[3832,4340,4162],{"class":3849},[3832,4342,4343],{"class":3853},"fetchTrips",[3832,4345,4183],{"class":3849},[3832,4347,4348],{"class":3853},"pending",[3832,4350,4351],{"class":3849},", (",[3832,4353,4354],{"class":3853},"state",[3832,4356,4313],{"class":3849},[3832,4358,4140],{"class":3889},[3832,4360,3897],{"class":3849},[3832,4362,4364,4367,4369,4372,4374],{"class":3834,"line":4363},47,[3832,4365,4366],{"class":3853},"                state",[3832,4368,4183],{"class":3849},[3832,4370,4371],{"class":3853},"isLoading",[3832,4373,4114],{"class":3849},[3832,4375,4376],{"class":3889},"true\n",[3832,4378,4380,4382,4384,4387,4389],{"class":3834,"line":4379},48,[3832,4381,4366],{"class":3853},[3832,4383,4183],{"class":3849},[3832,4385,4386],{"class":3853},"error",[3832,4388,4114],{"class":3849},[3832,4390,4391],{"class":3889},"null\n",[3832,4393,4395],{"class":3834,"line":4394},49,[3832,4396,4397],{"class":3849},"            })\n",[3832,4399,4401],{"class":3834,"line":4400},50,[3832,4402,4403],{"class":3838},"            \u002F\u002F Запит успішно завершився — зберігаємо дані\n",[3832,4405,4407,4409,4411,4413,4415,4417,4420,4422,4424,4426,4429,4431,4433],{"class":3834,"line":4406},51,[3832,4408,4335],{"class":3849},[3832,4410,4338],{"class":4117},[3832,4412,4162],{"class":3849},[3832,4414,4343],{"class":3853},[3832,4416,4183],{"class":3849},[3832,4418,4419],{"class":3853},"fulfilled",[3832,4421,4351],{"class":3849},[3832,4423,4354],{"class":3853},[3832,4425,3857],{"class":3849},[3832,4427,4428],{"class":3853},"action",[3832,4430,4313],{"class":3849},[3832,4432,4140],{"class":3889},[3832,4434,3897],{"class":3849},[3832,4436,4438,4440,4442,4444,4446],{"class":3834,"line":4437},52,[3832,4439,4366],{"class":3853},[3832,4441,4183],{"class":3849},[3832,4443,4371],{"class":3853},[3832,4445,4114],{"class":3849},[3832,4447,4448],{"class":3889},"false\n",[3832,4450,4452,4454,4456,4459,4461,4463,4465],{"class":3834,"line":4451},53,[3832,4453,4366],{"class":3853},[3832,4455,4183],{"class":3849},[3832,4457,4458],{"class":3853},"trips",[3832,4460,4114],{"class":3849},[3832,4462,4428],{"class":3853},[3832,4464,4183],{"class":3849},[3832,4466,4467],{"class":3853},"payload\n",[3832,4469,4471],{"class":3834,"line":4470},54,[3832,4472,4397],{"class":3849},[3832,4474,4476],{"class":3834,"line":4475},55,[3832,4477,4478],{"class":3838},"            \u002F\u002F Запит завершився помилкою — зберігаємо повідомлення\n",[3832,4480,4482,4484,4486,4488,4490,4492,4495,4497,4499,4501,4503,4505,4507],{"class":3834,"line":4481},56,[3832,4483,4335],{"class":3849},[3832,4485,4338],{"class":4117},[3832,4487,4162],{"class":3849},[3832,4489,4343],{"class":3853},[3832,4491,4183],{"class":3849},[3832,4493,4494],{"class":3853},"rejected",[3832,4496,4351],{"class":3849},[3832,4498,4354],{"class":3853},[3832,4500,3857],{"class":3849},[3832,4502,4428],{"class":3853},[3832,4504,4313],{"class":3849},[3832,4506,4140],{"class":3889},[3832,4508,3897],{"class":3849},[3832,4510,4512,4514,4516,4518,4520],{"class":3834,"line":4511},57,[3832,4513,4366],{"class":3853},[3832,4515,4183],{"class":3849},[3832,4517,4371],{"class":3853},[3832,4519,4114],{"class":3849},[3832,4521,4448],{"class":3889},[3832,4523,4525,4527,4529,4531,4533,4535,4537,4539,4541,4544,4547],{"class":3834,"line":4524},58,[3832,4526,4366],{"class":3853},[3832,4528,4183],{"class":3849},[3832,4530,4386],{"class":3853},[3832,4532,4114],{"class":3849},[3832,4534,4428],{"class":3853},[3832,4536,4183],{"class":3849},[3832,4538,4386],{"class":3853},[3832,4540,4183],{"class":3849},[3832,4542,4543],{"class":3853},"message",[3832,4545,4546],{"class":3849}," || ",[3832,4548,4549],{"class":3869},"'Невідома помилка'\n",[3832,4551,4553],{"class":3834,"line":4552},59,[3832,4554,4397],{"class":3849},[3832,4556,4558],{"class":3834,"line":4557},60,[3832,4559,4560],{"class":3849},"    },\n",[3832,4562,4564],{"class":3834,"line":4563},61,[3832,4565,4566],{"class":3849},"})\n",[3832,4568,4570],{"class":3834,"line":4569},62,[3832,4571,3877],{"emptyLinePlaceholder":3876},[3832,4573,4575,4577,4580,4582,4584],{"class":3834,"line":4574},63,[3832,4576,4105],{"class":3845},[3832,4578,4579],{"class":3845}," default",[3832,4581,4260],{"class":3853},[3832,4583,4183],{"class":3849},[3832,4585,4586],{"class":3853},"reducer\n",[3801,4588,4589],{},"Тепер у компоненті нам потрібно:",[3822,4591,4595],{"className":4592,"code":4593,"language":4594,"meta":3827,"style":3827},"language-tsx shiki shiki-themes light-plus dark-plus dark-plus","\u002F\u002F app\u002Fscreens\u002FTripsListScreen.tsx\nimport React, { useEffect } from 'react'\nimport { View, Text, FlatList, ActivityIndicator } from 'react-native'\nimport { useDispatch, useSelector } from 'react-redux'\nimport { fetchTrips } from '@\u002Fstore\u002FtripsSlice'\n\nexport function TripsListScreen() {\n    const dispatch = useDispatch()\n    \n    \u002F\u002F Отримуємо дані зі стору\n    const { trips, isLoading, error } = useSelector((state) => state.trips)\n\n    \u002F\u002F При монтуванні компонента запускаємо завантаження\n    useEffect(() => {\n        dispatch(fetchTrips())\n    }, [dispatch])\n\n    if (isLoading) {\n        return \u003CActivityIndicator size=\"large\" \u002F>\n    }\n\n    if (error) {\n        return \u003CText>Помилка: {error}\u003C\u002FText>\n    }\n\n    return (\n        \u003CFlatList\n            data={trips}\n            keyExtractor={(item) => item.id}\n            renderItem={({ item }) => \u003CText>{item.title}\u003C\u002FText>}\n        \u002F>\n    )\n}\n","tsx",[3829,4596,4597,4602,4622,4653,4674,4689,4693,4706,4720,4725,4730,4769,4773,4778,4790,4802,4813,4817,4828,4851,4855,4859,4869,4899,4903,4907,4915,4923,4936,4965,5009,5014,5019],{"__ignoreMap":3827},[3832,4598,4599],{"class":3834,"line":3835},[3832,4600,4601],{"class":3838},"\u002F\u002F app\u002Fscreens\u002FTripsListScreen.tsx\n",[3832,4603,4604,4606,4609,4612,4615,4617,4619],{"class":3834,"line":3842},[3832,4605,3846],{"class":3845},[3832,4607,4608],{"class":3853}," React",[3832,4610,4611],{"class":3849},", { ",[3832,4613,4614],{"class":3853},"useEffect",[3832,4616,3863],{"class":3849},[3832,4618,3866],{"class":3845},[3832,4620,4621],{"class":3869}," 'react'\n",[3832,4623,4624,4626,4628,4631,4633,4636,4638,4641,4643,4646,4648,4650],{"class":3834,"line":3873},[3832,4625,3846],{"class":3845},[3832,4627,3850],{"class":3849},[3832,4629,4630],{"class":3853},"View",[3832,4632,3857],{"class":3849},[3832,4634,4635],{"class":3853},"Text",[3832,4637,3857],{"class":3849},[3832,4639,4640],{"class":3853},"FlatList",[3832,4642,3857],{"class":3849},[3832,4644,4645],{"class":3853},"ActivityIndicator",[3832,4647,3863],{"class":3849},[3832,4649,3866],{"class":3845},[3832,4651,4652],{"class":3869}," 'react-native'\n",[3832,4654,4655,4657,4659,4662,4664,4667,4669,4671],{"class":3834,"line":3880},[3832,4656,3846],{"class":3845},[3832,4658,3850],{"class":3849},[3832,4660,4661],{"class":3853},"useDispatch",[3832,4663,3857],{"class":3849},[3832,4665,4666],{"class":3853},"useSelector",[3832,4668,3863],{"class":3849},[3832,4670,3866],{"class":3845},[3832,4672,4673],{"class":3869}," 'react-redux'\n",[3832,4675,4676,4678,4680,4682,4684,4686],{"class":3834,"line":3886},[3832,4677,3846],{"class":3845},[3832,4679,3850],{"class":3849},[3832,4681,4343],{"class":3853},[3832,4683,3863],{"class":3849},[3832,4685,3866],{"class":3845},[3832,4687,4688],{"class":3869}," '@\u002Fstore\u002FtripsSlice'\n",[3832,4690,4691],{"class":3834,"line":3900},[3832,4692,3877],{"emptyLinePlaceholder":3876},[3832,4694,4695,4697,4700,4703],{"class":3834,"line":3912},[3832,4696,4105],{"class":3845},[3832,4698,4699],{"class":3889}," function",[3832,4701,4702],{"class":4117}," TripsListScreen",[3832,4704,4705],{"class":3849},"() {\n",[3832,4707,4708,4711,4714,4716,4718],{"class":3834,"line":3922},[3832,4709,4710],{"class":3889},"    const",[3832,4712,4713],{"class":4042}," dispatch",[3832,4715,4114],{"class":3849},[3832,4717,4661],{"class":4117},[3832,4719,4230],{"class":3849},[3832,4721,4722],{"class":3834,"line":3932},[3832,4723,4724],{"class":3849},"    \n",[3832,4726,4727],{"class":3834,"line":3942},[3832,4728,4729],{"class":3838},"    \u002F\u002F Отримуємо дані зі стору\n",[3832,4731,4732,4734,4736,4738,4740,4742,4744,4746,4749,4751,4754,4756,4758,4760,4763,4765,4767],{"class":3834,"line":3948},[3832,4733,4710],{"class":3889},[3832,4735,3850],{"class":3849},[3832,4737,4458],{"class":4042},[3832,4739,3857],{"class":3849},[3832,4741,4371],{"class":4042},[3832,4743,3857],{"class":3849},[3832,4745,4386],{"class":4042},[3832,4747,4748],{"class":3849}," } = ",[3832,4750,4666],{"class":4117},[3832,4752,4753],{"class":3849},"((",[3832,4755,4354],{"class":3853},[3832,4757,4313],{"class":3849},[3832,4759,4140],{"class":3889},[3832,4761,4762],{"class":3853}," state",[3832,4764,4183],{"class":3849},[3832,4766,4458],{"class":3853},[3832,4768,4168],{"class":3849},[3832,4770,4771],{"class":3834,"line":3953},[3832,4772,3877],{"emptyLinePlaceholder":3876},[3832,4774,4775],{"class":3834,"line":3959},[3832,4776,4777],{"class":3838},"    \u002F\u002F При монтуванні компонента запускаємо завантаження\n",[3832,4779,4780,4783,4786,4788],{"class":3834,"line":3969},[3832,4781,4782],{"class":4117},"    useEffect",[3832,4784,4785],{"class":3849},"(() ",[3832,4787,4140],{"class":3889},[3832,4789,3897],{"class":3849},[3832,4791,4792,4795,4797,4799],{"class":3834,"line":3986},[3832,4793,4794],{"class":4117},"        dispatch",[3832,4796,4162],{"class":3849},[3832,4798,4343],{"class":4117},[3832,4800,4801],{"class":3849},"())\n",[3832,4803,4804,4807,4810],{"class":3834,"line":4000},[3832,4805,4806],{"class":3849},"    }, [",[3832,4808,4809],{"class":3853},"dispatch",[3832,4811,4812],{"class":3849},"])\n",[3832,4814,4815],{"class":3834,"line":4020},[3832,4816,3877],{"emptyLinePlaceholder":3876},[3832,4818,4819,4822,4824,4826],{"class":3834,"line":4025},[3832,4820,4821],{"class":3845},"    if",[3832,4823,4307],{"class":3849},[3832,4825,4371],{"class":3853},[3832,4827,4189],{"class":3849},[3832,4829,4830,4832,4836,4838,4842,4845,4848],{"class":3834,"line":4030},[3832,4831,4220],{"class":3845},[3832,4833,4835],{"class":4834},"s0P7L"," \u003C",[3832,4837,4645],{"class":3893},[3832,4839,4841],{"class":4840},"sa4r_"," size",[3832,4843,4844],{"class":3849},"=",[3832,4846,4847],{"class":3869},"\"large\"",[3832,4849,4850],{"class":4834}," \u002F>\n",[3832,4852,4853],{"class":3834,"line":4036},[3832,4854,4236],{"class":3849},[3832,4856,4857],{"class":3834,"line":4054},[3832,4858,3877],{"emptyLinePlaceholder":3876},[3832,4860,4861,4863,4865,4867],{"class":3834,"line":4063},[3832,4862,4821],{"class":3845},[3832,4864,4307],{"class":3849},[3832,4866,4386],{"class":3853},[3832,4868,4189],{"class":3849},[3832,4870,4871,4873,4875,4877,4880,4883,4886,4888,4891,4894,4896],{"class":3834,"line":4075},[3832,4872,4220],{"class":3845},[3832,4874,4835],{"class":4834},[3832,4876,4635],{"class":3893},[3832,4878,4879],{"class":4834},">",[3832,4881,4882],{"class":3849},"Помилка: ",[3832,4884,4885],{"class":3889},"{",[3832,4887,4386],{"class":3853},[3832,4889,4890],{"class":3889},"}",[3832,4892,4893],{"class":4834},"\u003C\u002F",[3832,4895,4635],{"class":3893},[3832,4897,4898],{"class":4834},">\n",[3832,4900,4901],{"class":3834,"line":4086},[3832,4902,4236],{"class":3849},[3832,4904,4905],{"class":3834,"line":4091},[3832,4906,3877],{"emptyLinePlaceholder":3876},[3832,4908,4909,4912],{"class":3834,"line":4096},[3832,4910,4911],{"class":3845},"    return",[3832,4913,4914],{"class":3849}," (\n",[3832,4916,4917,4920],{"class":3834,"line":4102},[3832,4918,4919],{"class":4834},"        \u003C",[3832,4921,4922],{"class":3893},"FlatList\n",[3832,4924,4925,4928,4930,4932,4934],{"class":3834,"line":4123},[3832,4926,4927],{"class":4840},"            data",[3832,4929,4844],{"class":3849},[3832,4931,4885],{"class":3889},[3832,4933,4458],{"class":3853},[3832,4935,3945],{"class":3889},[3832,4937,4938,4941,4943,4945,4948,4951,4953,4955,4958,4960,4963],{"class":3834,"line":4131},[3832,4939,4940],{"class":4840},"            keyExtractor",[3832,4942,4844],{"class":3849},[3832,4944,4885],{"class":3889},[3832,4946,4162],{"class":4947},"sD7JJ",[3832,4949,4950],{"class":3853},"item",[3832,4952,4313],{"class":4947},[3832,4954,4140],{"class":3889},[3832,4956,4957],{"class":3853}," item",[3832,4959,4183],{"class":4947},[3832,4961,4962],{"class":3853},"id",[3832,4964,3945],{"class":3889},[3832,4966,4967,4970,4972,4974,4977,4979,4982,4984,4986,4988,4990,4992,4994,4996,4999,5001,5003,5005,5007],{"class":3834,"line":4145},[3832,4968,4969],{"class":4840},"            renderItem",[3832,4971,4844],{"class":3849},[3832,4973,4885],{"class":3889},[3832,4975,4976],{"class":4947},"({ ",[3832,4978,4950],{"class":3853},[3832,4980,4981],{"class":4947}," }) ",[3832,4983,4140],{"class":3889},[3832,4985,4835],{"class":4834},[3832,4987,4635],{"class":3893},[3832,4989,4879],{"class":4834},[3832,4991,4885],{"class":3889},[3832,4993,4950],{"class":3853},[3832,4995,4183],{"class":4947},[3832,4997,4998],{"class":3853},"title",[3832,5000,4890],{"class":3889},[3832,5002,4893],{"class":4834},[3832,5004,4635],{"class":3893},[3832,5006,4879],{"class":4834},[3832,5008,3945],{"class":3889},[3832,5010,5011],{"class":3834,"line":4171},[3832,5012,5013],{"class":4834},"        \u002F>\n",[3832,5015,5016],{"class":3834,"line":4192},[3832,5017,5018],{"class":3849},"    )\n",[3832,5020,5021],{"class":3834,"line":4211},[3832,5022,3945],{"class":3849},[3801,5024,5025,5028],{},[3770,5026,5027],{},"Що ми вже написали:"," близько 80 рядків коду лише для одного простого GET-запиту! І це тільки початок проблем...",[3809,5030,5032],{"id":5031},"проблема-2-додавання-нової-поїздки","Проблема 2: Додавання нової поїздки",[3801,5034,5035],{},"Коли користувач створює нову поїздку, нам потрібно:",[3822,5037,5039],{"className":3824,"code":5038,"language":3826,"meta":3827,"style":3827},"\u002F\u002F Додаємо ще один thunk для створення поїздки\nexport const createTrip = createAsyncThunk(\n    'trips\u002FcreateTrip',\n    async (newTrip: Omit\u003CTrip, 'id'>) => {\n        const response = await fetch('http:\u002F\u002Flocalhost:3000\u002Ftrips', {\n            method: 'POST',\n            headers: { 'Content-Type': 'application\u002Fjson' },\n            body: JSON.stringify(newTrip),\n        })\n        return response.json()\n    }\n)\n\n\u002F\u002F Розширюємо extraReducers ще трьома кейсами\nextraReducers: (builder) => {\n    \u002F\u002F ... попередні кейси для fetchTrips\n    builder\n        .addCase(createTrip.pending, (state) => {\n            state.isLoading = true\n        })\n        .addCase(createTrip.fulfilled, (state, action) => {\n            state.isLoading = false\n            \u002F\u002F Додаємо нову поїздку до списку\n            state.trips.push(action.payload)\n        })\n        .addCase(createTrip.rejected, (state, action) => {\n            state.isLoading = false\n            state.error = action.error.message || 'Помилка створення'\n        })\n}\n",[3829,5040,5041,5046,5061,5068,5099,5118,5128,5146,5166,5171,5183,5187,5191,5195,5200,5217,5222,5227,5253,5266,5270,5298,5310,5315,5339,5343,5371,5383,5408,5412],{"__ignoreMap":3827},[3832,5042,5043],{"class":3834,"line":3835},[3832,5044,5045],{"class":3838},"\u002F\u002F Додаємо ще один thunk для створення поїздки\n",[3832,5047,5048,5050,5052,5055,5057,5059],{"class":3834,"line":3842},[3832,5049,4105],{"class":3845},[3832,5051,4108],{"class":3889},[3832,5053,5054],{"class":4042}," createTrip",[3832,5056,4114],{"class":3849},[3832,5058,3860],{"class":4117},[3832,5060,4120],{"class":3849},[3832,5062,5063,5066],{"class":3834,"line":3873},[3832,5064,5065],{"class":3869},"    'trips\u002FcreateTrip'",[3832,5067,4072],{"class":3849},[3832,5069,5070,5072,5074,5077,5079,5082,5085,5087,5089,5092,5095,5097],{"class":3834,"line":3880},[3832,5071,4134],{"class":3889},[3832,5073,4307],{"class":3849},[3832,5075,5076],{"class":3853},"newTrip",[3832,5078,3906],{"class":3849},[3832,5080,5081],{"class":3893},"Omit",[3832,5083,5084],{"class":3849},"\u003C",[3832,5086,3977],{"class":3893},[3832,5088,3857],{"class":3849},[3832,5090,5091],{"class":3869},"'id'",[3832,5093,5094],{"class":3849},">) ",[3832,5096,4140],{"class":3889},[3832,5098,3897],{"class":3849},[3832,5100,5101,5103,5105,5107,5109,5111,5113,5115],{"class":3834,"line":3886},[3832,5102,4148],{"class":3889},[3832,5104,4151],{"class":4042},[3832,5106,4114],{"class":3849},[3832,5108,4156],{"class":3845},[3832,5110,4159],{"class":4117},[3832,5112,4162],{"class":3849},[3832,5114,4165],{"class":3869},[3832,5116,5117],{"class":3849},", {\n",[3832,5119,5120,5123,5126],{"class":3834,"line":3900},[3832,5121,5122],{"class":3853},"            method:",[3832,5124,5125],{"class":3869}," 'POST'",[3832,5127,4072],{"class":3849},[3832,5129,5130,5133,5135,5138,5140,5143],{"class":3834,"line":3912},[3832,5131,5132],{"class":3853},"            headers:",[3832,5134,3850],{"class":3849},[3832,5136,5137],{"class":3869},"'Content-Type'",[3832,5139,4304],{"class":3853},[3832,5141,5142],{"class":3869}," 'application\u002Fjson'",[3832,5144,5145],{"class":3849}," },\n",[3832,5147,5148,5151,5154,5156,5159,5161,5163],{"class":3834,"line":3922},[3832,5149,5150],{"class":3853},"            body:",[3832,5152,5153],{"class":4042}," JSON",[3832,5155,4183],{"class":3849},[3832,5157,5158],{"class":4117},"stringify",[3832,5160,4162],{"class":3849},[3832,5162,5076],{"class":3853},[3832,5164,5165],{"class":3849},"),\n",[3832,5167,5168],{"class":3834,"line":3932},[3832,5169,5170],{"class":3849},"        })\n",[3832,5172,5173,5175,5177,5179,5181],{"class":3834,"line":3942},[3832,5174,4220],{"class":3845},[3832,5176,4151],{"class":3853},[3832,5178,4183],{"class":3849},[3832,5180,4227],{"class":4117},[3832,5182,4230],{"class":3849},[3832,5184,5185],{"class":3834,"line":3948},[3832,5186,4236],{"class":3849},[3832,5188,5189],{"class":3834,"line":3953},[3832,5190,4168],{"class":3849},[3832,5192,5193],{"class":3834,"line":3959},[3832,5194,3877],{"emptyLinePlaceholder":3876},[3832,5196,5197],{"class":3834,"line":3969},[3832,5198,5199],{"class":3838},"\u002F\u002F Розширюємо extraReducers ще трьома кейсами\n",[3832,5201,5202,5206,5209,5211,5213,5215],{"class":3834,"line":3986},[3832,5203,5205],{"class":5204},"s5IvJ","extraReducers",[3832,5207,5208],{"class":3849},": (",[3832,5210,4310],{"class":3853},[3832,5212,4313],{"class":3849},[3832,5214,4140],{"class":3889},[3832,5216,3897],{"class":3849},[3832,5218,5219],{"class":3834,"line":4000},[3832,5220,5221],{"class":3838},"    \u002F\u002F ... попередні кейси для fetchTrips\n",[3832,5223,5224],{"class":3834,"line":4020},[3832,5225,5226],{"class":3853},"    builder\n",[3832,5228,5229,5232,5234,5236,5239,5241,5243,5245,5247,5249,5251],{"class":3834,"line":4025},[3832,5230,5231],{"class":3849},"        .",[3832,5233,4338],{"class":4117},[3832,5235,4162],{"class":3849},[3832,5237,5238],{"class":3853},"createTrip",[3832,5240,4183],{"class":3849},[3832,5242,4348],{"class":3853},[3832,5244,4351],{"class":3849},[3832,5246,4354],{"class":3853},[3832,5248,4313],{"class":3849},[3832,5250,4140],{"class":3889},[3832,5252,3897],{"class":3849},[3832,5254,5255,5258,5260,5262,5264],{"class":3834,"line":4030},[3832,5256,5257],{"class":3853},"            state",[3832,5259,4183],{"class":3849},[3832,5261,4371],{"class":3853},[3832,5263,4114],{"class":3849},[3832,5265,4376],{"class":3889},[3832,5267,5268],{"class":3834,"line":4036},[3832,5269,5170],{"class":3849},[3832,5271,5272,5274,5276,5278,5280,5282,5284,5286,5288,5290,5292,5294,5296],{"class":3834,"line":4054},[3832,5273,5231],{"class":3849},[3832,5275,4338],{"class":4117},[3832,5277,4162],{"class":3849},[3832,5279,5238],{"class":3853},[3832,5281,4183],{"class":3849},[3832,5283,4419],{"class":3853},[3832,5285,4351],{"class":3849},[3832,5287,4354],{"class":3853},[3832,5289,3857],{"class":3849},[3832,5291,4428],{"class":3853},[3832,5293,4313],{"class":3849},[3832,5295,4140],{"class":3889},[3832,5297,3897],{"class":3849},[3832,5299,5300,5302,5304,5306,5308],{"class":3834,"line":4063},[3832,5301,5257],{"class":3853},[3832,5303,4183],{"class":3849},[3832,5305,4371],{"class":3853},[3832,5307,4114],{"class":3849},[3832,5309,4448],{"class":3889},[3832,5311,5312],{"class":3834,"line":4075},[3832,5313,5314],{"class":3838},"            \u002F\u002F Додаємо нову поїздку до списку\n",[3832,5316,5317,5319,5321,5323,5325,5328,5330,5332,5334,5337],{"class":3834,"line":4086},[3832,5318,5257],{"class":3853},[3832,5320,4183],{"class":3849},[3832,5322,4458],{"class":3853},[3832,5324,4183],{"class":3849},[3832,5326,5327],{"class":4117},"push",[3832,5329,4162],{"class":3849},[3832,5331,4428],{"class":3853},[3832,5333,4183],{"class":3849},[3832,5335,5336],{"class":3853},"payload",[3832,5338,4168],{"class":3849},[3832,5340,5341],{"class":3834,"line":4091},[3832,5342,5170],{"class":3849},[3832,5344,5345,5347,5349,5351,5353,5355,5357,5359,5361,5363,5365,5367,5369],{"class":3834,"line":4096},[3832,5346,5231],{"class":3849},[3832,5348,4338],{"class":4117},[3832,5350,4162],{"class":3849},[3832,5352,5238],{"class":3853},[3832,5354,4183],{"class":3849},[3832,5356,4494],{"class":3853},[3832,5358,4351],{"class":3849},[3832,5360,4354],{"class":3853},[3832,5362,3857],{"class":3849},[3832,5364,4428],{"class":3853},[3832,5366,4313],{"class":3849},[3832,5368,4140],{"class":3889},[3832,5370,3897],{"class":3849},[3832,5372,5373,5375,5377,5379,5381],{"class":3834,"line":4102},[3832,5374,5257],{"class":3853},[3832,5376,4183],{"class":3849},[3832,5378,4371],{"class":3853},[3832,5380,4114],{"class":3849},[3832,5382,4448],{"class":3889},[3832,5384,5385,5387,5389,5391,5393,5395,5397,5399,5401,5403,5405],{"class":3834,"line":4123},[3832,5386,5257],{"class":3853},[3832,5388,4183],{"class":3849},[3832,5390,4386],{"class":3853},[3832,5392,4114],{"class":3849},[3832,5394,4428],{"class":3853},[3832,5396,4183],{"class":3849},[3832,5398,4386],{"class":3853},[3832,5400,4183],{"class":3849},[3832,5402,4543],{"class":3853},[3832,5404,4546],{"class":3849},[3832,5406,5407],{"class":3869},"'Помилка створення'\n",[3832,5409,5410],{"class":3834,"line":4131},[3832,5411,5170],{"class":3849},[3832,5413,5414],{"class":3834,"line":4145},[3832,5415,3945],{"class":3849},[3801,5417,5418,5421],{},[3770,5419,5420],{},"Проблема:"," Кожен новий ендпоінт вимагає ще 10-15 рядків однотипного коду!",[3809,5423,5425],{"id":5424},"проблема-3-синхронізація-між-екранами","Проблема 3: Синхронізація між екранами",[3801,5427,5428],{},"Тепер уявіть типовий сценарій користувача:",[5430,5431,5432,5436,5439,5443,5446,5450],"steps",{},[3809,5433,5435],{"id":5434},"крок-1-користувач-відкриває-список-поїздок","Крок 1: Користувач відкриває список поїздок",[3801,5437,5438],{},"Застосунок завантажує дані з сервера, показує 5 поїздок. Дані зберігаються у Redux store.",[3809,5440,5442],{"id":5441},"крок-2-користувач-переходить-на-інший-екран","Крок 2: Користувач переходить на інший екран",[3801,5444,5445],{},"Відкривається форма \"Створити нову поїздку\". Користувач заповнює поля та натискає \"Зберегти\".",[3809,5447,5449],{"id":5448},"крок-3-користувач-повертається-назад","Крок 3: Користувач повертається назад",[3801,5451,5452],{},"Що має показати екран списку? Старі 5 поїздок чи нові 6?",[3801,5454,5455],{},"При традиційному підході у вас є три варіанти:",[5457,5458,5459,5545,5622],"tabs",{},[5460,5461,5463,5539],"tabs-item",{"label":5462},"Варіант 1: Перезавантажити все",[3822,5464,5466],{"className":4592,"code":5465,"language":4594,"meta":3827,"style":3827},"\u002F\u002F Після створення поїздки перезавантажуємо весь список\nasync function handleCreateTrip(newTrip) {\n    await dispatch(createTrip(newTrip))\n    await dispatch(fetchTrips())  \u002F\u002F Повторний запит до сервера\n    navigation.goBack()\n}\n",[3829,5467,5468,5473,5489,5507,5523,5535],{"__ignoreMap":3827},[3832,5469,5470],{"class":3834,"line":3835},[3832,5471,5472],{"class":3838},"\u002F\u002F Після створення поїздки перезавантажуємо весь список\n",[3832,5474,5475,5478,5480,5483,5485,5487],{"class":3834,"line":3842},[3832,5476,5477],{"class":3889},"async",[3832,5479,4699],{"class":3889},[3832,5481,5482],{"class":4117}," handleCreateTrip",[3832,5484,4162],{"class":3849},[3832,5486,5076],{"class":3853},[3832,5488,4189],{"class":3849},[3832,5490,5491,5494,5496,5498,5500,5502,5504],{"class":3834,"line":3873},[3832,5492,5493],{"class":3845},"    await",[3832,5495,4713],{"class":4117},[3832,5497,4162],{"class":3849},[3832,5499,5238],{"class":4117},[3832,5501,4162],{"class":3849},[3832,5503,5076],{"class":3853},[3832,5505,5506],{"class":3849},"))\n",[3832,5508,5509,5511,5513,5515,5517,5520],{"class":3834,"line":3880},[3832,5510,5493],{"class":3845},[3832,5512,4713],{"class":4117},[3832,5514,4162],{"class":3849},[3832,5516,4343],{"class":4117},[3832,5518,5519],{"class":3849},"())  ",[3832,5521,5522],{"class":3838},"\u002F\u002F Повторний запит до сервера\n",[3832,5524,5525,5528,5530,5533],{"class":3834,"line":3886},[3832,5526,5527],{"class":3853},"    navigation",[3832,5529,4183],{"class":3849},[3832,5531,5532],{"class":4117},"goBack",[3832,5534,4230],{"class":3849},[3832,5536,5537],{"class":3834,"line":3900},[3832,5538,3945],{"class":3849},[3801,5540,5541,5544],{},[3770,5542,5543],{},"Недолік:"," Зайвий мережевий запит. Якщо у списку було 100 поїздок, ми завантажуємо усі 101 знову, хоча потрібна лише одна нова.",[5460,5546,5548,5613],{"label":5547},"Варіант 2: Оновити локально",[3822,5549,5551],{"className":4592,"code":5550,"language":4594,"meta":3827,"style":3827},"\u002F\u002F Просто додаємо нову поїздку до масиву в сторі\n.addCase(createTrip.fulfilled, (state, action) => {\n    state.trips.push(action.payload)\n})\n",[3829,5552,5553,5558,5586,5609],{"__ignoreMap":3827},[3832,5554,5555],{"class":3834,"line":3835},[3832,5556,5557],{"class":3838},"\u002F\u002F Просто додаємо нову поїздку до масиву в сторі\n",[3832,5559,5560,5562,5564,5566,5568,5570,5572,5574,5576,5578,5580,5582,5584],{"class":3834,"line":3842},[3832,5561,4183],{"class":3849},[3832,5563,4338],{"class":4117},[3832,5565,4162],{"class":3849},[3832,5567,5238],{"class":3853},[3832,5569,4183],{"class":3849},[3832,5571,4419],{"class":3853},[3832,5573,4351],{"class":3849},[3832,5575,4354],{"class":3853},[3832,5577,3857],{"class":3849},[3832,5579,4428],{"class":3853},[3832,5581,4313],{"class":3849},[3832,5583,4140],{"class":3889},[3832,5585,3897],{"class":3849},[3832,5587,5588,5591,5593,5595,5597,5599,5601,5603,5605,5607],{"class":3834,"line":3873},[3832,5589,5590],{"class":3853},"    state",[3832,5592,4183],{"class":3849},[3832,5594,4458],{"class":3853},[3832,5596,4183],{"class":3849},[3832,5598,5327],{"class":4117},[3832,5600,4162],{"class":3849},[3832,5602,4428],{"class":3853},[3832,5604,4183],{"class":3849},[3832,5606,5336],{"class":3853},[3832,5608,4168],{"class":3849},[3832,5610,5611],{"class":3834,"line":3880},[3832,5612,4566],{"class":3849},[3801,5614,5615,5617,5618,5621],{},[3770,5616,5543],{}," Якщо інший користувач теж додав поїздку через веб-версію, ми про це не дізнаємось. Дані застаріють (",[3817,5619,5620],{},"stale data",").",[5460,5623,5625,5792],{"label":5624},"Варіант 3: Складна логіка синхронізації",[3822,5626,5628],{"className":4592,"code":5627,"language":4594,"meta":3827,"style":3827},"\u002F\u002F Відслідковуємо час останнього оновлення\ninterface TripsState {\n    trips: Trip[]\n    lastFetched: number | null\n    \u002F\u002F ... інші поля\n}\n\n\u002F\u002F Перезавантажуємо лише якщо пройшло більше 5 хвилин\nuseEffect(() => {\n    const now = Date.now()\n    const fiveMinutes = 5 * 60 * 1000\n    \n    if (!lastFetched || now - lastFetched > fiveMinutes) {\n        dispatch(fetchTrips())\n    }\n}, [lastFetched])\n",[3829,5629,5630,5635,5643,5654,5668,5673,5677,5681,5686,5696,5715,5739,5743,5769,5779,5783],{"__ignoreMap":3827},[3832,5631,5632],{"class":3834,"line":3835},[3832,5633,5634],{"class":3838},"\u002F\u002F Відслідковуємо час останнього оновлення\n",[3832,5636,5637,5639,5641],{"class":3834,"line":3842},[3832,5638,3890],{"class":3889},[3832,5640,3964],{"class":3893},[3832,5642,3897],{"class":3849},[3832,5644,5645,5647,5649,5651],{"class":3834,"line":3873},[3832,5646,3972],{"class":3853},[3832,5648,3906],{"class":3849},[3832,5650,3977],{"class":3893},[3832,5652,5653],{"class":3849},"[]\n",[3832,5655,5656,5659,5661,5664,5666],{"class":3834,"line":3880},[3832,5657,5658],{"class":3853},"    lastFetched",[3832,5660,3906],{"class":3849},[3832,5662,5663],{"class":3893},"number",[3832,5665,4011],{"class":3849},[3832,5667,4391],{"class":3893},[3832,5669,5670],{"class":3834,"line":3886},[3832,5671,5672],{"class":3838},"    \u002F\u002F ... інші поля\n",[3832,5674,5675],{"class":3834,"line":3900},[3832,5676,3945],{"class":3849},[3832,5678,5679],{"class":3834,"line":3912},[3832,5680,3877],{"emptyLinePlaceholder":3876},[3832,5682,5683],{"class":3834,"line":3922},[3832,5684,5685],{"class":3838},"\u002F\u002F Перезавантажуємо лише якщо пройшло більше 5 хвилин\n",[3832,5687,5688,5690,5692,5694],{"class":3834,"line":3932},[3832,5689,4614],{"class":4117},[3832,5691,4785],{"class":3849},[3832,5693,4140],{"class":3889},[3832,5695,3897],{"class":3849},[3832,5697,5698,5700,5703,5705,5708,5710,5713],{"class":3834,"line":3942},[3832,5699,4710],{"class":3889},[3832,5701,5702],{"class":4042}," now",[3832,5704,4114],{"class":3849},[3832,5706,5707],{"class":3853},"Date",[3832,5709,4183],{"class":3849},[3832,5711,5712],{"class":4117},"now",[3832,5714,4230],{"class":3849},[3832,5716,5717,5719,5722,5724,5728,5731,5734,5736],{"class":3834,"line":3948},[3832,5718,4710],{"class":3889},[3832,5720,5721],{"class":4042}," fiveMinutes",[3832,5723,4114],{"class":3849},[3832,5725,5727],{"class":5726},"sJj4R","5",[3832,5729,5730],{"class":3849}," * ",[3832,5732,5733],{"class":5726},"60",[3832,5735,5730],{"class":3849},[3832,5737,5738],{"class":5726},"1000\n",[3832,5740,5741],{"class":3834,"line":3953},[3832,5742,4724],{"class":3849},[3832,5744,5745,5747,5749,5752,5754,5756,5759,5761,5764,5767],{"class":3834,"line":3959},[3832,5746,4821],{"class":3845},[3832,5748,4177],{"class":3849},[3832,5750,5751],{"class":3853},"lastFetched",[3832,5753,4546],{"class":3849},[3832,5755,5712],{"class":3853},[3832,5757,5758],{"class":3849}," - ",[3832,5760,5751],{"class":3853},[3832,5762,5763],{"class":3849}," > ",[3832,5765,5766],{"class":3853},"fiveMinutes",[3832,5768,4189],{"class":3849},[3832,5770,5771,5773,5775,5777],{"class":3834,"line":3969},[3832,5772,4794],{"class":4117},[3832,5774,4162],{"class":3849},[3832,5776,4343],{"class":4117},[3832,5778,4801],{"class":3849},[3832,5780,5781],{"class":3834,"line":3986},[3832,5782,4236],{"class":3849},[3832,5784,5785,5788,5790],{"class":3834,"line":4000},[3832,5786,5787],{"class":3849},"}, [",[3832,5789,5751],{"class":3853},[3832,5791,4812],{"class":3849},[3801,5793,5794,5796],{},[3770,5795,5543],{}," Дуже багато коду для простої задачі! І це ще не враховує інші сценарії...",[3809,5798,5800],{"id":5799},"проблема-4-мобільна-специфіка","Проблема 4: Мобільна специфіка",[3801,5802,5803],{},"У мобільному застосунку користувач може:",[3746,5805,5806,5812,5818],{},[3749,5807,5808,5811],{},[3770,5809,5810],{},"Згорнути застосунок"," (перейти в інший додаток)",[3749,5813,5814,5817],{},[3770,5815,5816],{},"Втратити інтернет"," (зайти в метро)",[3749,5819,5820,5823],{},[3770,5821,5822],{},"Відновити з'єднання"," (вийти з метро)",[3801,5825,5826],{},"При ручному підході вам потрібно писати такий код:",[3822,5828,5830],{"className":4592,"code":5829,"language":4594,"meta":3827,"style":3827},"import { AppState } from 'react-native'\nimport NetInfo from '@react-native-community\u002Fnetinfo'\n\n\u002F\u002F Відслідковуємо стан застосунку\nuseEffect(() => {\n    const subscription = AppState.addEventListener('change', (nextAppState) => {\n        if (nextAppState === 'active') {\n            \u002F\u002F Застосунок знову активний — перезавантажити дані?\n            dispatch(fetchTrips())\n        }\n    })\n    return () => subscription.remove()\n}, [])\n\n\u002F\u002F Відслідковуємо стан мережі\nuseEffect(() => {\n    const unsubscribe = NetInfo.addEventListener((state) => {\n        if (state.isConnected) {\n            \u002F\u002F Інтернет відновлено — перезавантажити дані?\n            dispatch(fetchTrips())\n        }\n    })\n    return () => unsubscribe()\n}, [])\n",[3829,5831,5832,5847,5860,5864,5869,5879,5911,5927,5932,5943,5947,5952,5969,5974,5978,5983,5993,6019,6034,6039,6049,6053,6057,6069],{"__ignoreMap":3827},[3832,5833,5834,5836,5838,5841,5843,5845],{"class":3834,"line":3835},[3832,5835,3846],{"class":3845},[3832,5837,3850],{"class":3849},[3832,5839,5840],{"class":3853},"AppState",[3832,5842,3863],{"class":3849},[3832,5844,3866],{"class":3845},[3832,5846,4652],{"class":3869},[3832,5848,5849,5851,5854,5857],{"class":3834,"line":3842},[3832,5850,3846],{"class":3845},[3832,5852,5853],{"class":3853}," NetInfo",[3832,5855,5856],{"class":3845}," from",[3832,5858,5859],{"class":3869}," '@react-native-community\u002Fnetinfo'\n",[3832,5861,5862],{"class":3834,"line":3873},[3832,5863,3877],{"emptyLinePlaceholder":3876},[3832,5865,5866],{"class":3834,"line":3880},[3832,5867,5868],{"class":3838},"\u002F\u002F Відслідковуємо стан застосунку\n",[3832,5870,5871,5873,5875,5877],{"class":3834,"line":3886},[3832,5872,4614],{"class":4117},[3832,5874,4785],{"class":3849},[3832,5876,4140],{"class":3889},[3832,5878,3897],{"class":3849},[3832,5880,5881,5883,5886,5888,5890,5892,5895,5897,5900,5902,5905,5907,5909],{"class":3834,"line":3900},[3832,5882,4710],{"class":3889},[3832,5884,5885],{"class":4042}," subscription",[3832,5887,4114],{"class":3849},[3832,5889,5840],{"class":3853},[3832,5891,4183],{"class":3849},[3832,5893,5894],{"class":4117},"addEventListener",[3832,5896,4162],{"class":3849},[3832,5898,5899],{"class":3869},"'change'",[3832,5901,4351],{"class":3849},[3832,5903,5904],{"class":3853},"nextAppState",[3832,5906,4313],{"class":3849},[3832,5908,4140],{"class":3889},[3832,5910,3897],{"class":3849},[3832,5912,5913,5915,5917,5919,5922,5925],{"class":3834,"line":3912},[3832,5914,4174],{"class":3845},[3832,5916,4307],{"class":3849},[3832,5918,5904],{"class":3853},[3832,5920,5921],{"class":3849}," === ",[3832,5923,5924],{"class":3869},"'active'",[3832,5926,4189],{"class":3849},[3832,5928,5929],{"class":3834,"line":3922},[3832,5930,5931],{"class":3838},"            \u002F\u002F Застосунок знову активний — перезавантажити дані?\n",[3832,5933,5934,5937,5939,5941],{"class":3834,"line":3932},[3832,5935,5936],{"class":4117},"            dispatch",[3832,5938,4162],{"class":3849},[3832,5940,4343],{"class":4117},[3832,5942,4801],{"class":3849},[3832,5944,5945],{"class":3834,"line":3942},[3832,5946,4214],{"class":3849},[3832,5948,5949],{"class":3834,"line":3948},[3832,5950,5951],{"class":3849},"    })\n",[3832,5953,5954,5956,5958,5960,5962,5964,5967],{"class":3834,"line":3953},[3832,5955,4911],{"class":3845},[3832,5957,4137],{"class":3849},[3832,5959,4140],{"class":3889},[3832,5961,5885],{"class":3853},[3832,5963,4183],{"class":3849},[3832,5965,5966],{"class":4117},"remove",[3832,5968,4230],{"class":3849},[3832,5970,5971],{"class":3834,"line":3959},[3832,5972,5973],{"class":3849},"}, [])\n",[3832,5975,5976],{"class":3834,"line":3969},[3832,5977,3877],{"emptyLinePlaceholder":3876},[3832,5979,5980],{"class":3834,"line":3986},[3832,5981,5982],{"class":3838},"\u002F\u002F Відслідковуємо стан мережі\n",[3832,5984,5985,5987,5989,5991],{"class":3834,"line":4000},[3832,5986,4614],{"class":4117},[3832,5988,4785],{"class":3849},[3832,5990,4140],{"class":3889},[3832,5992,3897],{"class":3849},[3832,5994,5995,5997,6000,6002,6005,6007,6009,6011,6013,6015,6017],{"class":3834,"line":4020},[3832,5996,4710],{"class":3889},[3832,5998,5999],{"class":4042}," unsubscribe",[3832,6001,4114],{"class":3849},[3832,6003,6004],{"class":3853},"NetInfo",[3832,6006,4183],{"class":3849},[3832,6008,5894],{"class":4117},[3832,6010,4753],{"class":3849},[3832,6012,4354],{"class":3853},[3832,6014,4313],{"class":3849},[3832,6016,4140],{"class":3889},[3832,6018,3897],{"class":3849},[3832,6020,6021,6023,6025,6027,6029,6032],{"class":3834,"line":4025},[3832,6022,4174],{"class":3845},[3832,6024,4307],{"class":3849},[3832,6026,4354],{"class":3853},[3832,6028,4183],{"class":3849},[3832,6030,6031],{"class":3853},"isConnected",[3832,6033,4189],{"class":3849},[3832,6035,6036],{"class":3834,"line":4030},[3832,6037,6038],{"class":3838},"            \u002F\u002F Інтернет відновлено — перезавантажити дані?\n",[3832,6040,6041,6043,6045,6047],{"class":3834,"line":4036},[3832,6042,5936],{"class":4117},[3832,6044,4162],{"class":3849},[3832,6046,4343],{"class":4117},[3832,6048,4801],{"class":3849},[3832,6050,6051],{"class":3834,"line":4054},[3832,6052,4214],{"class":3849},[3832,6054,6055],{"class":3834,"line":4063},[3832,6056,5951],{"class":3849},[3832,6058,6059,6061,6063,6065,6067],{"class":3834,"line":4075},[3832,6060,4911],{"class":3845},[3832,6062,4137],{"class":3849},[3832,6064,4140],{"class":3889},[3832,6066,5999],{"class":4117},[3832,6068,4230],{"class":3849},[3832,6070,6071],{"class":3834,"line":4086},[3832,6072,5973],{"class":3849},[3801,6074,6075,6077],{},[3770,6076,5420],{}," Цей код потрібно дублювати у кожному компоненті, який працює з серверними даними!",[3809,6079,6081],{"id":6080},"підсумок-проблем-традиційного-підходу","Підсумок проблем традиційного підходу",[6083,6084,6085,6090,6117],"warning",{},[3801,6086,6087],{},[3770,6088,6089],{},"Для роботи з серверними даними через традиційний Redux + createAsyncThunk вам потрібно:",[3746,6091,6092,6095,6105,6108,6111,6114],{},[3749,6093,6094],{},"Створювати окремий thunk для кожного ендпоінта (GET, POST, PUT, DELETE)",[3749,6096,6097,6098,3857,6100,3857,6102,6104],{},"Вручну описувати стани ",[3829,6099,4348],{},[3829,6101,4419],{},[3829,6103,4494],{}," для кожної дії",[3749,6106,6107],{},"Самостійно керувати кешуванням та застарілими даними",[3749,6109,6110],{},"Дублювати логіку відслідковування фокусу та мережі в кожному компоненті",[3749,6112,6113],{},"Писати складну логіку синхронізації між різними екранами",[3749,6115,6116],{},"Обробляти паралельні запити та дедуплікацію вручну",[3801,6118,6119,6122],{},[3770,6120,6121],{},"Результат:"," Сотні рядків однотипного коду, який важко підтримувати та тестувати.",[3809,6124,6126],{"id":6125},"рішення-rtk-query-автоматизує-все-це","Рішення: RTK Query автоматизує все це",[3801,6128,6129,4307,6132,6134],{},[3770,6130,6131],{},"RTK Query",[3817,6133,6131],{},") — це офіційне розширення Redux Toolkit, яке повністю автоматизує роботу з серверними даними. Ось як виглядає той самий функціонал з RTK Query:",[3822,6136,6138],{"className":3824,"code":6137,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fservices\u002FtripsApi.ts — ПІДХІД RTK QUERY\nimport { createApi, fetchBaseQuery } from '@reduxjs\u002Ftoolkit\u002Fquery\u002Freact'\n\ninterface Trip {\n    id: string\n    title: string\n    region: string\n    startDate: string\n}\n\n\u002F\u002F Описуємо API один раз — RTK Query згенерує все інше автоматично\nexport const tripsApi = createApi({\n    reducerPath: 'tripsApi',\n    baseQuery: fetchBaseQuery({ baseUrl: 'http:\u002F\u002Flocalhost:3000' }),\n    tagTypes: ['Trip'],  \u002F\u002F Для автоматичної інвалідації кешу\n    endpoints: (builder) => ({\n        \u002F\u002F Ендпоінт для отримання списку\n        getTrips: builder.query\u003CTrip[], void>({\n            query: () => '\u002Ftrips',\n            providesTags: ['Trip'],  \u002F\u002F Цей запит надає дані типу Trip\n        }),\n        \u002F\u002F Ендпоінт для створення нової поїздки\n        createTrip: builder.mutation\u003CTrip, Omit\u003CTrip, 'id'>>({\n            query: (newTrip) => ({\n                url: '\u002Ftrips',\n                method: 'POST',\n                body: newTrip,\n            }),\n            invalidatesTags: ['Trip'],  \u002F\u002F Автоматично оновити getTrips\n        }),\n    }),\n})\n\n\u002F\u002F RTK Query автоматично створює хуки для кожного ендпоінта\nexport const { useGetTripsQuery, useCreateTripMutation } = tripsApi\n",[3829,6139,6140,6145,6166,6170,6178,6186,6194,6202,6210,6214,6218,6223,6238,6248,6267,6284,6302,6307,6333,6349,6363,6368,6373,6404,6420,6429,6438,6448,6453,6467,6471,6476,6480,6484,6489],{"__ignoreMap":3827},[3832,6141,6142],{"class":3834,"line":3835},[3832,6143,6144],{"class":3838},"\u002F\u002F src\u002Fservices\u002FtripsApi.ts — ПІДХІД RTK QUERY\n",[3832,6146,6147,6149,6151,6154,6156,6159,6161,6163],{"class":3834,"line":3842},[3832,6148,3846],{"class":3845},[3832,6150,3850],{"class":3849},[3832,6152,6153],{"class":3853},"createApi",[3832,6155,3857],{"class":3849},[3832,6157,6158],{"class":3853},"fetchBaseQuery",[3832,6160,3863],{"class":3849},[3832,6162,3866],{"class":3845},[3832,6164,6165],{"class":3869}," '@reduxjs\u002Ftoolkit\u002Fquery\u002Freact'\n",[3832,6167,6168],{"class":3834,"line":3873},[3832,6169,3877],{"emptyLinePlaceholder":3876},[3832,6171,6172,6174,6176],{"class":3834,"line":3880},[3832,6173,3890],{"class":3889},[3832,6175,3894],{"class":3893},[3832,6177,3897],{"class":3849},[3832,6179,6180,6182,6184],{"class":3834,"line":3886},[3832,6181,3903],{"class":3853},[3832,6183,3906],{"class":3849},[3832,6185,3909],{"class":3893},[3832,6187,6188,6190,6192],{"class":3834,"line":3900},[3832,6189,3915],{"class":3853},[3832,6191,3906],{"class":3849},[3832,6193,3909],{"class":3893},[3832,6195,6196,6198,6200],{"class":3834,"line":3912},[3832,6197,3925],{"class":3853},[3832,6199,3906],{"class":3849},[3832,6201,3909],{"class":3893},[3832,6203,6204,6206,6208],{"class":3834,"line":3922},[3832,6205,3935],{"class":3853},[3832,6207,3906],{"class":3849},[3832,6209,3909],{"class":3893},[3832,6211,6212],{"class":3834,"line":3932},[3832,6213,3945],{"class":3849},[3832,6215,6216],{"class":3834,"line":3942},[3832,6217,3877],{"emptyLinePlaceholder":3876},[3832,6219,6220],{"class":3834,"line":3948},[3832,6221,6222],{"class":3838},"\u002F\u002F Описуємо API один раз — RTK Query згенерує все інше автоматично\n",[3832,6224,6225,6227,6229,6232,6234,6236],{"class":3834,"line":3953},[3832,6226,4105],{"class":3845},[3832,6228,4108],{"class":3889},[3832,6230,6231],{"class":4042}," tripsApi",[3832,6233,4114],{"class":3849},[3832,6235,6153],{"class":4117},[3832,6237,4267],{"class":3849},[3832,6239,6240,6243,6246],{"class":3834,"line":3959},[3832,6241,6242],{"class":3853},"    reducerPath:",[3832,6244,6245],{"class":3869}," 'tripsApi'",[3832,6247,4072],{"class":3849},[3832,6249,6250,6253,6256,6258,6261,6264],{"class":3834,"line":3969},[3832,6251,6252],{"class":3853},"    baseQuery:",[3832,6254,6255],{"class":4117}," fetchBaseQuery",[3832,6257,4976],{"class":3849},[3832,6259,6260],{"class":3853},"baseUrl:",[3832,6262,6263],{"class":3869}," 'http:\u002F\u002Flocalhost:3000'",[3832,6265,6266],{"class":3849}," }),\n",[3832,6268,6269,6272,6275,6278,6281],{"class":3834,"line":3986},[3832,6270,6271],{"class":3853},"    tagTypes:",[3832,6273,6274],{"class":3849}," [",[3832,6276,6277],{"class":3869},"'Trip'",[3832,6279,6280],{"class":3849},"],  ",[3832,6282,6283],{"class":3838},"\u002F\u002F Для автоматичної інвалідації кешу\n",[3832,6285,6286,6289,6291,6293,6295,6297,6299],{"class":3834,"line":4000},[3832,6287,6288],{"class":4117},"    endpoints",[3832,6290,4304],{"class":3853},[3832,6292,4307],{"class":3849},[3832,6294,4310],{"class":3853},[3832,6296,4313],{"class":3849},[3832,6298,4140],{"class":3889},[3832,6300,6301],{"class":3849}," ({\n",[3832,6303,6304],{"class":3834,"line":4020},[3832,6305,6306],{"class":3838},"        \u002F\u002F Ендпоінт для отримання списку\n",[3832,6308,6309,6312,6315,6317,6320,6322,6324,6327,6330],{"class":3834,"line":4025},[3832,6310,6311],{"class":3853},"        getTrips:",[3832,6313,6314],{"class":3853}," builder",[3832,6316,4183],{"class":3849},[3832,6318,6319],{"class":4117},"query",[3832,6321,5084],{"class":3849},[3832,6323,3977],{"class":3893},[3832,6325,6326],{"class":3849},"[], ",[3832,6328,6329],{"class":3893},"void",[3832,6331,6332],{"class":3849},">({\n",[3832,6334,6335,6338,6340,6342,6344,6347],{"class":3834,"line":4030},[3832,6336,6337],{"class":4117},"            query",[3832,6339,4304],{"class":3853},[3832,6341,4137],{"class":3849},[3832,6343,4140],{"class":3889},[3832,6345,6346],{"class":3869}," '\u002Ftrips'",[3832,6348,4072],{"class":3849},[3832,6350,6351,6354,6356,6358,6360],{"class":3834,"line":4036},[3832,6352,6353],{"class":3853},"            providesTags:",[3832,6355,6274],{"class":3849},[3832,6357,6277],{"class":3869},[3832,6359,6280],{"class":3849},[3832,6361,6362],{"class":3838},"\u002F\u002F Цей запит надає дані типу Trip\n",[3832,6364,6365],{"class":3834,"line":4054},[3832,6366,6367],{"class":3849},"        }),\n",[3832,6369,6370],{"class":3834,"line":4063},[3832,6371,6372],{"class":3838},"        \u002F\u002F Ендпоінт для створення нової поїздки\n",[3832,6374,6375,6378,6380,6382,6385,6387,6389,6391,6393,6395,6397,6399,6401],{"class":3834,"line":4075},[3832,6376,6377],{"class":3853},"        createTrip:",[3832,6379,6314],{"class":3853},[3832,6381,4183],{"class":3849},[3832,6383,6384],{"class":4117},"mutation",[3832,6386,5084],{"class":3849},[3832,6388,3977],{"class":3893},[3832,6390,3857],{"class":3849},[3832,6392,5081],{"class":3893},[3832,6394,5084],{"class":3849},[3832,6396,3977],{"class":3893},[3832,6398,3857],{"class":3849},[3832,6400,5091],{"class":3869},[3832,6402,6403],{"class":3849},">>({\n",[3832,6405,6406,6408,6410,6412,6414,6416,6418],{"class":3834,"line":4086},[3832,6407,6337],{"class":4117},[3832,6409,4304],{"class":3853},[3832,6411,4307],{"class":3849},[3832,6413,5076],{"class":3853},[3832,6415,4313],{"class":3849},[3832,6417,4140],{"class":3889},[3832,6419,6301],{"class":3849},[3832,6421,6422,6425,6427],{"class":3834,"line":4091},[3832,6423,6424],{"class":3853},"                url:",[3832,6426,6346],{"class":3869},[3832,6428,4072],{"class":3849},[3832,6430,6431,6434,6436],{"class":3834,"line":4096},[3832,6432,6433],{"class":3853},"                method:",[3832,6435,5125],{"class":3869},[3832,6437,4072],{"class":3849},[3832,6439,6440,6443,6446],{"class":3834,"line":4102},[3832,6441,6442],{"class":3853},"                body:",[3832,6444,6445],{"class":3853}," newTrip",[3832,6447,4072],{"class":3849},[3832,6449,6450],{"class":3834,"line":4123},[3832,6451,6452],{"class":3849},"            }),\n",[3832,6454,6455,6458,6460,6462,6464],{"class":3834,"line":4131},[3832,6456,6457],{"class":3853},"            invalidatesTags:",[3832,6459,6274],{"class":3849},[3832,6461,6277],{"class":3869},[3832,6463,6280],{"class":3849},[3832,6465,6466],{"class":3838},"\u002F\u002F Автоматично оновити getTrips\n",[3832,6468,6469],{"class":3834,"line":4145},[3832,6470,6367],{"class":3849},[3832,6472,6473],{"class":3834,"line":4171},[3832,6474,6475],{"class":3849},"    }),\n",[3832,6477,6478],{"class":3834,"line":4192},[3832,6479,4566],{"class":3849},[3832,6481,6482],{"class":3834,"line":4211},[3832,6483,3877],{"emptyLinePlaceholder":3876},[3832,6485,6486],{"class":3834,"line":4217},[3832,6487,6488],{"class":3838},"\u002F\u002F RTK Query автоматично створює хуки для кожного ендпоінта\n",[3832,6490,6491,6493,6495,6497,6500,6502,6505,6507],{"class":3834,"line":4233},[3832,6492,4105],{"class":3845},[3832,6494,4108],{"class":3889},[3832,6496,3850],{"class":3849},[3832,6498,6499],{"class":4042},"useGetTripsQuery",[3832,6501,3857],{"class":3849},[3832,6503,6504],{"class":4042},"useCreateTripMutation",[3832,6506,4748],{"class":3849},[3832,6508,6509],{"class":3853},"tripsApi\n",[3801,6511,6512],{},"Тепер у компоненті весь код зводиться до:",[3822,6514,6516],{"className":4592,"code":6515,"language":4594,"meta":3827,"style":3827},"\u002F\u002F app\u002Fscreens\u002FTripsListScreen.tsx — З RTK QUERY\nimport { useGetTripsQuery } from '@\u002Fservices\u002FtripsApi'\n\nexport function TripsListScreen() {\n    \u002F\u002F Один хук замінює весь попередній код!\n    const { data: trips, isLoading, error } = useGetTripsQuery()\n\n    if (isLoading) return \u003CActivityIndicator \u002F>\n    if (error) return \u003CText>Помилка завантаження\u003C\u002FText>\n\n    return (\n        \u003CFlatList\n            data={trips}\n            keyExtractor={(item) => item.id}\n            renderItem={({ item }) => \u003CText>{item.title}\u003C\u002FText>}\n        \u002F>\n    )\n}\n",[3829,6517,6518,6523,6538,6542,6552,6557,6584,6588,6607,6634,6638,6644,6650,6662,6686,6726,6730,6734],{"__ignoreMap":3827},[3832,6519,6520],{"class":3834,"line":3835},[3832,6521,6522],{"class":3838},"\u002F\u002F app\u002Fscreens\u002FTripsListScreen.tsx — З RTK QUERY\n",[3832,6524,6525,6527,6529,6531,6533,6535],{"class":3834,"line":3842},[3832,6526,3846],{"class":3845},[3832,6528,3850],{"class":3849},[3832,6530,6499],{"class":3853},[3832,6532,3863],{"class":3849},[3832,6534,3866],{"class":3845},[3832,6536,6537],{"class":3869}," '@\u002Fservices\u002FtripsApi'\n",[3832,6539,6540],{"class":3834,"line":3873},[3832,6541,3877],{"emptyLinePlaceholder":3876},[3832,6543,6544,6546,6548,6550],{"class":3834,"line":3880},[3832,6545,4105],{"class":3845},[3832,6547,4699],{"class":3889},[3832,6549,4702],{"class":4117},[3832,6551,4705],{"class":3849},[3832,6553,6554],{"class":3834,"line":3886},[3832,6555,6556],{"class":3838},"    \u002F\u002F Один хук замінює весь попередній код!\n",[3832,6558,6559,6561,6563,6566,6568,6570,6572,6574,6576,6578,6580,6582],{"class":3834,"line":3900},[3832,6560,4710],{"class":3889},[3832,6562,3850],{"class":3849},[3832,6564,6565],{"class":3853},"data",[3832,6567,3906],{"class":3849},[3832,6569,4458],{"class":4042},[3832,6571,3857],{"class":3849},[3832,6573,4371],{"class":4042},[3832,6575,3857],{"class":3849},[3832,6577,4386],{"class":4042},[3832,6579,4748],{"class":3849},[3832,6581,6499],{"class":4117},[3832,6583,4230],{"class":3849},[3832,6585,6586],{"class":3834,"line":3912},[3832,6587,3877],{"emptyLinePlaceholder":3876},[3832,6589,6590,6592,6594,6596,6598,6601,6603,6605],{"class":3834,"line":3922},[3832,6591,4821],{"class":3845},[3832,6593,4307],{"class":3849},[3832,6595,4371],{"class":3853},[3832,6597,4313],{"class":3849},[3832,6599,6600],{"class":3845},"return",[3832,6602,4835],{"class":4834},[3832,6604,4645],{"class":3893},[3832,6606,4850],{"class":4834},[3832,6608,6609,6611,6613,6615,6617,6619,6621,6623,6625,6628,6630,6632],{"class":3834,"line":3932},[3832,6610,4821],{"class":3845},[3832,6612,4307],{"class":3849},[3832,6614,4386],{"class":3853},[3832,6616,4313],{"class":3849},[3832,6618,6600],{"class":3845},[3832,6620,4835],{"class":4834},[3832,6622,4635],{"class":3893},[3832,6624,4879],{"class":4834},[3832,6626,6627],{"class":3849},"Помилка завантаження",[3832,6629,4893],{"class":4834},[3832,6631,4635],{"class":3893},[3832,6633,4898],{"class":4834},[3832,6635,6636],{"class":3834,"line":3942},[3832,6637,3877],{"emptyLinePlaceholder":3876},[3832,6639,6640,6642],{"class":3834,"line":3948},[3832,6641,4911],{"class":3845},[3832,6643,4914],{"class":3849},[3832,6645,6646,6648],{"class":3834,"line":3953},[3832,6647,4919],{"class":4834},[3832,6649,4922],{"class":3893},[3832,6651,6652,6654,6656,6658,6660],{"class":3834,"line":3959},[3832,6653,4927],{"class":4840},[3832,6655,4844],{"class":3849},[3832,6657,4885],{"class":3889},[3832,6659,4458],{"class":3853},[3832,6661,3945],{"class":3889},[3832,6663,6664,6666,6668,6670,6672,6674,6676,6678,6680,6682,6684],{"class":3834,"line":3969},[3832,6665,4940],{"class":4840},[3832,6667,4844],{"class":3849},[3832,6669,4885],{"class":3889},[3832,6671,4162],{"class":4947},[3832,6673,4950],{"class":3853},[3832,6675,4313],{"class":4947},[3832,6677,4140],{"class":3889},[3832,6679,4957],{"class":3853},[3832,6681,4183],{"class":4947},[3832,6683,4962],{"class":3853},[3832,6685,3945],{"class":3889},[3832,6687,6688,6690,6692,6694,6696,6698,6700,6702,6704,6706,6708,6710,6712,6714,6716,6718,6720,6722,6724],{"class":3834,"line":3986},[3832,6689,4969],{"class":4840},[3832,6691,4844],{"class":3849},[3832,6693,4885],{"class":3889},[3832,6695,4976],{"class":4947},[3832,6697,4950],{"class":3853},[3832,6699,4981],{"class":4947},[3832,6701,4140],{"class":3889},[3832,6703,4835],{"class":4834},[3832,6705,4635],{"class":3893},[3832,6707,4879],{"class":4834},[3832,6709,4885],{"class":3889},[3832,6711,4950],{"class":3853},[3832,6713,4183],{"class":4947},[3832,6715,4998],{"class":3853},[3832,6717,4890],{"class":3889},[3832,6719,4893],{"class":4834},[3832,6721,4635],{"class":3893},[3832,6723,4879],{"class":4834},[3832,6725,3945],{"class":3889},[3832,6727,6728],{"class":3834,"line":4000},[3832,6729,5013],{"class":4834},[3832,6731,6732],{"class":3834,"line":4020},[3832,6733,5018],{"class":3849},[3832,6735,6736],{"class":3834,"line":4025},[3832,6737,3945],{"class":3849},[3801,6739,6740],{},[3770,6741,6742],{},"Що RTK Query робить автоматично:",[3738,6744,6745,6753,6769,6782],{},[3741,6746,6748,6749,6752],{"icon":2675,"title":6747},"⚡ Автоматичний кеш","Після першого завантаження дані зберігаються в пам'яті. Повторні виклики ",[3829,6750,6751],{},"useGetTripsQuery()"," на інших екранах миттєво повертають закешовані дані без нових мережевих запитів.",[3741,6754,6757,6758,6760,6761,6764,6765,6768],{"icon":6755,"title":6756},"i-lucide-refresh-cw","🔄 Розумна інвалідація","Коли ви створюєте нову поїздку через ",[3829,6759,5238],{},", RTK Query автоматично бачить тег ",[3829,6762,6763],{},"invalidatesTags: ['Trip']"," та перезавантажує усі запити з ",[3829,6766,6767],{},"providesTags: ['Trip']",". Список оновлюється сам!",[3741,6770,6773,6774,6777,6778,6781],{"icon":6771,"title":6772},"i-lucide-smartphone","📱 Мобільна оптимізація","Вбудована підтримка ",[3829,6775,6776],{},"refetchOnFocus"," (перезавантаження при поверненні з фону) та ",[3829,6779,6780],{},"refetchOnReconnect"," (при відновленні інтернету). Вмикається одним рядком конфігурації.",[3741,6783,6786,6787,6789,6790,6793],{"icon":6784,"title":6785},"i-lucide-git-merge","🎯 Дедуплікація запитів","Якщо 5 компонентів одночасно викликають ",[3829,6788,6751],{},", RTK Query відправить лише ",[3770,6791,6792],{},"один"," реальний HTTP-запит. Всі компоненти отримають той самий результат.",[6795,6796,6797,6810,6824],"note",{},[3801,6798,6799,6802,6803,6806,6807,5621],{},[3770,6800,6801],{},"Головний висновок:"," RTK Query розуміє, що серверний стан (",[3817,6804,6805],{},"Server State",") принципово відрізняється від клієнтського (",[3817,6808,6809],{},"Client State",[3746,6811,6812,6818],{},[3749,6813,6814,6817],{},[3770,6815,6816],{},"Клієнтський стан"," — це дані, які живуть лише у вашому застосунку (налаштування теми, поточна вкладка, текст у полі вводу). Вони завжди актуальні, бо належать вам.",[3749,6819,6820,6823],{},[3770,6821,6822],{},"Серверний стан"," — це дані, першоджерело яких знаходиться на віддаленому сервері. Вони можуть застаріти, можуть змінитися іншими користувачами, вимагають мережевих запитів та спеціальної логіки кешування.",[3801,6825,6826],{},"RTK Query — це спеціалізований інструмент для автоматизації всього життєвого циклу серверного стану у React Native застосунках.",[3793,6828],{},[3796,6830,6832],{"id":6831},"розуміння-різниці-клієнтський-стан-vs-серверний-стан","Розуміння різниці: Клієнтський стан vs Серверний стан",[3801,6834,6835],{},"Перед тим як почати працювати з RTK Query, критично важливо зрозуміти фундаментальну різницю між двома типами даних у вашому застосунку. Це визначить, коли використовувати звичайний Redux слайс, а коли — RTK Query.",[3809,6837,6839],{"id":6838},"що-таке-клієнтський-стан","Що таке клієнтський стан?",[3801,6841,6842,4307,6844,6846,6847,6850],{},[3770,6843,6816],{},[3817,6845,6809],{},") — це дані, які ",[3770,6848,6849],{},"повністю належать вашому застосунку"," та існують тільки на пристрої користувача. Ці дані завжди актуальні, бо їх джерело знаходиться у самому застосунку.",[6852,6853,6855],"h4",{"id":6854},"практичні-приклади-клієнтського-стану","Практичні приклади клієнтського стану",[3801,6857,6858],{},"Давайте розглянемо конкретні приклади з реального мобільного застосунку:",[6860,6861,6862],"code-group",{},[3822,6863,6866],{"className":3824,"code":6864,"filename":6865,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fstore\u002FthemeSlice.ts\nimport { createSlice } from '@reduxjs\u002Ftoolkit'\n\ninterface ThemeState {\n    mode: 'light' | 'dark'\n    fontSize: 'small' | 'medium' | 'large'\n}\n\nconst themeSlice = createSlice({\n    name: 'theme',\n    initialState: {\n        mode: 'light',\n        fontSize: 'medium',\n    } as ThemeState,\n    reducers: {\n        toggleTheme: (state) => {\n            \u002F\u002F Це чисто локальна зміна — не потрібен сервер\n            state.mode = state.mode === 'light' ? 'dark' : 'light'\n        },\n        setFontSize: (state, action) => {\n            state.fontSize = action.payload\n        },\n    },\n})\n","Налаштування теми",[3829,6867,6868,6873,6887,6891,6900,6915,6935,6939,6943,6956,6965,6972,6982,6992,7004,7010,7027,7032,7065,7070,7091,7108,7112,7116],{"__ignoreMap":3827},[3832,6869,6870],{"class":3834,"line":3835},[3832,6871,6872],{"class":3838},"\u002F\u002F src\u002Fstore\u002FthemeSlice.ts\n",[3832,6874,6875,6877,6879,6881,6883,6885],{"class":3834,"line":3842},[3832,6876,3846],{"class":3845},[3832,6878,3850],{"class":3849},[3832,6880,3854],{"class":3853},[3832,6882,3863],{"class":3849},[3832,6884,3866],{"class":3845},[3832,6886,3870],{"class":3869},[3832,6888,6889],{"class":3834,"line":3873},[3832,6890,3877],{"emptyLinePlaceholder":3876},[3832,6892,6893,6895,6898],{"class":3834,"line":3880},[3832,6894,3890],{"class":3889},[3832,6896,6897],{"class":3893}," ThemeState",[3832,6899,3897],{"class":3849},[3832,6901,6902,6905,6907,6910,6912],{"class":3834,"line":3886},[3832,6903,6904],{"class":3853},"    mode",[3832,6906,3906],{"class":3849},[3832,6908,6909],{"class":3869},"'light'",[3832,6911,4011],{"class":3849},[3832,6913,6914],{"class":3869},"'dark'\n",[3832,6916,6917,6920,6922,6925,6927,6930,6932],{"class":3834,"line":3900},[3832,6918,6919],{"class":3853},"    fontSize",[3832,6921,3906],{"class":3849},[3832,6923,6924],{"class":3869},"'small'",[3832,6926,4011],{"class":3849},[3832,6928,6929],{"class":3869},"'medium'",[3832,6931,4011],{"class":3849},[3832,6933,6934],{"class":3869},"'large'\n",[3832,6936,6937],{"class":3834,"line":3912},[3832,6938,3945],{"class":3849},[3832,6940,6941],{"class":3834,"line":3922},[3832,6942,3877],{"emptyLinePlaceholder":3876},[3832,6944,6945,6947,6950,6952,6954],{"class":3834,"line":3932},[3832,6946,4039],{"class":3889},[3832,6948,6949],{"class":4042}," themeSlice",[3832,6951,4114],{"class":3849},[3832,6953,3854],{"class":4117},[3832,6955,4267],{"class":3849},[3832,6957,6958,6960,6963],{"class":3834,"line":3942},[3832,6959,4273],{"class":3853},[3832,6961,6962],{"class":3869}," 'theme'",[3832,6964,4072],{"class":3849},[3832,6966,6967,6970],{"class":3834,"line":3948},[3832,6968,6969],{"class":3853},"    initialState:",[3832,6971,3897],{"class":3849},[3832,6973,6974,6977,6980],{"class":3834,"line":3953},[3832,6975,6976],{"class":3853},"        mode:",[3832,6978,6979],{"class":3869}," 'light'",[3832,6981,4072],{"class":3849},[3832,6983,6984,6987,6990],{"class":3834,"line":3959},[3832,6985,6986],{"class":3853},"        fontSize:",[3832,6988,6989],{"class":3869}," 'medium'",[3832,6991,4072],{"class":3849},[3832,6993,6994,6997,7000,7002],{"class":3834,"line":3969},[3832,6995,6996],{"class":3849},"    } ",[3832,6998,6999],{"class":3845},"as",[3832,7001,6897],{"class":3893},[3832,7003,4072],{"class":3849},[3832,7005,7006,7008],{"class":3834,"line":3986},[3832,7007,4292],{"class":3853},[3832,7009,3897],{"class":3849},[3832,7011,7012,7015,7017,7019,7021,7023,7025],{"class":3834,"line":4000},[3832,7013,7014],{"class":4117},"        toggleTheme",[3832,7016,4304],{"class":3853},[3832,7018,4307],{"class":3849},[3832,7020,4354],{"class":3853},[3832,7022,4313],{"class":3849},[3832,7024,4140],{"class":3889},[3832,7026,3897],{"class":3849},[3832,7028,7029],{"class":3834,"line":4020},[3832,7030,7031],{"class":3838},"            \u002F\u002F Це чисто локальна зміна — не потрібен сервер\n",[3832,7033,7034,7036,7038,7041,7043,7045,7047,7049,7051,7053,7056,7059,7062],{"class":3834,"line":4025},[3832,7035,5257],{"class":3853},[3832,7037,4183],{"class":3849},[3832,7039,7040],{"class":3853},"mode",[3832,7042,4114],{"class":3849},[3832,7044,4354],{"class":3853},[3832,7046,4183],{"class":3849},[3832,7048,7040],{"class":3853},[3832,7050,5921],{"class":3849},[3832,7052,6909],{"class":3869},[3832,7054,7055],{"class":3849}," ? ",[3832,7057,7058],{"class":3869},"'dark'",[3832,7060,7061],{"class":3849}," : ",[3832,7063,7064],{"class":3869},"'light'\n",[3832,7066,7067],{"class":3834,"line":4030},[3832,7068,7069],{"class":3849},"        },\n",[3832,7071,7072,7075,7077,7079,7081,7083,7085,7087,7089],{"class":3834,"line":4036},[3832,7073,7074],{"class":4117},"        setFontSize",[3832,7076,4304],{"class":3853},[3832,7078,4307],{"class":3849},[3832,7080,4354],{"class":3853},[3832,7082,3857],{"class":3849},[3832,7084,4428],{"class":3853},[3832,7086,4313],{"class":3849},[3832,7088,4140],{"class":3889},[3832,7090,3897],{"class":3849},[3832,7092,7093,7095,7097,7100,7102,7104,7106],{"class":3834,"line":4054},[3832,7094,5257],{"class":3853},[3832,7096,4183],{"class":3849},[3832,7098,7099],{"class":3853},"fontSize",[3832,7101,4114],{"class":3849},[3832,7103,4428],{"class":3853},[3832,7105,4183],{"class":3849},[3832,7107,4467],{"class":3853},[3832,7109,7110],{"class":3834,"line":4063},[3832,7111,7069],{"class":3849},[3832,7113,7114],{"class":3834,"line":4075},[3832,7115,4560],{"class":3849},[3832,7117,7118],{"class":3834,"line":4086},[3832,7119,4566],{"class":3849},[3822,7121,7124],{"className":3824,"code":7122,"filename":7123,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fstore\u002FuiSlice.ts\nimport { createSlice } from '@reduxjs\u002Ftoolkit'\n\ninterface UIState {\n    activeTab: 'home' | 'trips' | 'profile'\n    isMenuOpen: boolean\n    selectedTripId: string | null\n}\n\nconst uiSlice = createSlice({\n    name: 'ui',\n    initialState: {\n        activeTab: 'home',\n        isMenuOpen: false,\n        selectedTripId: null,\n    } as UIState,\n    reducers: {\n        setActiveTab: (state, action) => {\n            state.activeTab = action.payload\n        },\n        openMenu: (state) => {\n            state.isMenuOpen = true\n        },\n        closeMenu: (state) => {\n            state.isMenuOpen = false\n        },\n    },\n})\n","Стан UI елементів",[3829,7125,7126,7131,7145,7149,7158,7178,7188,7201,7205,7209,7222,7231,7237,7247,7256,7265,7275,7281,7302,7319,7323,7340,7353,7357,7374,7386,7390,7394],{"__ignoreMap":3827},[3832,7127,7128],{"class":3834,"line":3835},[3832,7129,7130],{"class":3838},"\u002F\u002F src\u002Fstore\u002FuiSlice.ts\n",[3832,7132,7133,7135,7137,7139,7141,7143],{"class":3834,"line":3842},[3832,7134,3846],{"class":3845},[3832,7136,3850],{"class":3849},[3832,7138,3854],{"class":3853},[3832,7140,3863],{"class":3849},[3832,7142,3866],{"class":3845},[3832,7144,3870],{"class":3869},[3832,7146,7147],{"class":3834,"line":3873},[3832,7148,3877],{"emptyLinePlaceholder":3876},[3832,7150,7151,7153,7156],{"class":3834,"line":3880},[3832,7152,3890],{"class":3889},[3832,7154,7155],{"class":3893}," UIState",[3832,7157,3897],{"class":3849},[3832,7159,7160,7163,7165,7168,7170,7173,7175],{"class":3834,"line":3886},[3832,7161,7162],{"class":3853},"    activeTab",[3832,7164,3906],{"class":3849},[3832,7166,7167],{"class":3869},"'home'",[3832,7169,4011],{"class":3849},[3832,7171,7172],{"class":3869},"'trips'",[3832,7174,4011],{"class":3849},[3832,7176,7177],{"class":3869},"'profile'\n",[3832,7179,7180,7183,7185],{"class":3834,"line":3900},[3832,7181,7182],{"class":3853},"    isMenuOpen",[3832,7184,3906],{"class":3849},[3832,7186,7187],{"class":3893},"boolean\n",[3832,7189,7190,7193,7195,7197,7199],{"class":3834,"line":3912},[3832,7191,7192],{"class":3853},"    selectedTripId",[3832,7194,3906],{"class":3849},[3832,7196,4008],{"class":3893},[3832,7198,4011],{"class":3849},[3832,7200,4391],{"class":3893},[3832,7202,7203],{"class":3834,"line":3922},[3832,7204,3945],{"class":3849},[3832,7206,7207],{"class":3834,"line":3932},[3832,7208,3877],{"emptyLinePlaceholder":3876},[3832,7210,7211,7213,7216,7218,7220],{"class":3834,"line":3942},[3832,7212,4039],{"class":3889},[3832,7214,7215],{"class":4042}," uiSlice",[3832,7217,4114],{"class":3849},[3832,7219,3854],{"class":4117},[3832,7221,4267],{"class":3849},[3832,7223,7224,7226,7229],{"class":3834,"line":3948},[3832,7225,4273],{"class":3853},[3832,7227,7228],{"class":3869}," 'ui'",[3832,7230,4072],{"class":3849},[3832,7232,7233,7235],{"class":3834,"line":3953},[3832,7234,6969],{"class":3853},[3832,7236,3897],{"class":3849},[3832,7238,7239,7242,7245],{"class":3834,"line":3959},[3832,7240,7241],{"class":3853},"        activeTab:",[3832,7243,7244],{"class":3869}," 'home'",[3832,7246,4072],{"class":3849},[3832,7248,7249,7252,7254],{"class":3834,"line":3969},[3832,7250,7251],{"class":3853},"        isMenuOpen:",[3832,7253,4069],{"class":3889},[3832,7255,4072],{"class":3849},[3832,7257,7258,7261,7263],{"class":3834,"line":3986},[3832,7259,7260],{"class":3853},"        selectedTripId:",[3832,7262,4081],{"class":3889},[3832,7264,4072],{"class":3849},[3832,7266,7267,7269,7271,7273],{"class":3834,"line":4000},[3832,7268,6996],{"class":3849},[3832,7270,6999],{"class":3845},[3832,7272,7155],{"class":3893},[3832,7274,4072],{"class":3849},[3832,7276,7277,7279],{"class":3834,"line":4020},[3832,7278,4292],{"class":3853},[3832,7280,3897],{"class":3849},[3832,7282,7283,7286,7288,7290,7292,7294,7296,7298,7300],{"class":3834,"line":4025},[3832,7284,7285],{"class":4117},"        setActiveTab",[3832,7287,4304],{"class":3853},[3832,7289,4307],{"class":3849},[3832,7291,4354],{"class":3853},[3832,7293,3857],{"class":3849},[3832,7295,4428],{"class":3853},[3832,7297,4313],{"class":3849},[3832,7299,4140],{"class":3889},[3832,7301,3897],{"class":3849},[3832,7303,7304,7306,7308,7311,7313,7315,7317],{"class":3834,"line":4030},[3832,7305,5257],{"class":3853},[3832,7307,4183],{"class":3849},[3832,7309,7310],{"class":3853},"activeTab",[3832,7312,4114],{"class":3849},[3832,7314,4428],{"class":3853},[3832,7316,4183],{"class":3849},[3832,7318,4467],{"class":3853},[3832,7320,7321],{"class":3834,"line":4036},[3832,7322,7069],{"class":3849},[3832,7324,7325,7328,7330,7332,7334,7336,7338],{"class":3834,"line":4054},[3832,7326,7327],{"class":4117},"        openMenu",[3832,7329,4304],{"class":3853},[3832,7331,4307],{"class":3849},[3832,7333,4354],{"class":3853},[3832,7335,4313],{"class":3849},[3832,7337,4140],{"class":3889},[3832,7339,3897],{"class":3849},[3832,7341,7342,7344,7346,7349,7351],{"class":3834,"line":4063},[3832,7343,5257],{"class":3853},[3832,7345,4183],{"class":3849},[3832,7347,7348],{"class":3853},"isMenuOpen",[3832,7350,4114],{"class":3849},[3832,7352,4376],{"class":3889},[3832,7354,7355],{"class":3834,"line":4075},[3832,7356,7069],{"class":3849},[3832,7358,7359,7362,7364,7366,7368,7370,7372],{"class":3834,"line":4086},[3832,7360,7361],{"class":4117},"        closeMenu",[3832,7363,4304],{"class":3853},[3832,7365,4307],{"class":3849},[3832,7367,4354],{"class":3853},[3832,7369,4313],{"class":3849},[3832,7371,4140],{"class":3889},[3832,7373,3897],{"class":3849},[3832,7375,7376,7378,7380,7382,7384],{"class":3834,"line":4091},[3832,7377,5257],{"class":3853},[3832,7379,4183],{"class":3849},[3832,7381,7348],{"class":3853},[3832,7383,4114],{"class":3849},[3832,7385,4448],{"class":3889},[3832,7387,7388],{"class":3834,"line":4096},[3832,7389,7069],{"class":3849},[3832,7391,7392],{"class":3834,"line":4102},[3832,7393,4560],{"class":3849},[3832,7395,7396],{"class":3834,"line":4123},[3832,7397,4566],{"class":3849},[3801,7399,7400],{},"::",[3822,7402,7405],{"className":4592,"code":7403,"filename":7404,"language":4594,"meta":3827,"style":3827},"\u002F\u002F Навіть простіше — через useState\nfunction CreateTripForm() {\n    const [title, setTitle] = useState('')\n    const [region, setRegion] = useState('')\n    const [date, setDate] = useState(new Date())\n    \n    \u002F\u002F Ці дані живуть тільки у компоненті\n    \u002F\u002F Вони зникають при розмонтуванні\n    return (\n        \u003CView>\n            \u003CTextInput \n                value={title} \n                onChangeText={setTitle}\n                placeholder=\"Назва поїздки\"\n            \u002F>\n            {\u002F* ... інші поля *\u002F}\n        \u003C\u002FView>\n    )\n}\n","Локальний стан форми",[3829,7406,7407,7412,7422,7448,7472,7500,7504,7509,7514,7520,7528,7539,7554,7567,7577,7582,7592,7601,7605],{"__ignoreMap":3827},[3832,7408,7409],{"class":3834,"line":3835},[3832,7410,7411],{"class":3838},"\u002F\u002F Навіть простіше — через useState\n",[3832,7413,7414,7417,7420],{"class":3834,"line":3842},[3832,7415,7416],{"class":3889},"function",[3832,7418,7419],{"class":4117}," CreateTripForm",[3832,7421,4705],{"class":3849},[3832,7423,7424,7426,7428,7430,7432,7435,7438,7441,7443,7446],{"class":3834,"line":3873},[3832,7425,4710],{"class":3889},[3832,7427,6274],{"class":3849},[3832,7429,4998],{"class":4042},[3832,7431,3857],{"class":3849},[3832,7433,7434],{"class":4042},"setTitle",[3832,7436,7437],{"class":3849},"] = ",[3832,7439,7440],{"class":4117},"useState",[3832,7442,4162],{"class":3849},[3832,7444,7445],{"class":3869},"''",[3832,7447,4168],{"class":3849},[3832,7449,7450,7452,7454,7457,7459,7462,7464,7466,7468,7470],{"class":3834,"line":3880},[3832,7451,4710],{"class":3889},[3832,7453,6274],{"class":3849},[3832,7455,7456],{"class":4042},"region",[3832,7458,3857],{"class":3849},[3832,7460,7461],{"class":4042},"setRegion",[3832,7463,7437],{"class":3849},[3832,7465,7440],{"class":4117},[3832,7467,4162],{"class":3849},[3832,7469,7445],{"class":3869},[3832,7471,4168],{"class":3849},[3832,7473,7474,7476,7478,7481,7483,7486,7488,7490,7492,7495,7498],{"class":3834,"line":3886},[3832,7475,4710],{"class":3889},[3832,7477,6274],{"class":3849},[3832,7479,7480],{"class":4042},"date",[3832,7482,3857],{"class":3849},[3832,7484,7485],{"class":4042},"setDate",[3832,7487,7437],{"class":3849},[3832,7489,7440],{"class":4117},[3832,7491,4162],{"class":3849},[3832,7493,7494],{"class":3889},"new",[3832,7496,7497],{"class":4117}," Date",[3832,7499,4801],{"class":3849},[3832,7501,7502],{"class":3834,"line":3900},[3832,7503,4724],{"class":3849},[3832,7505,7506],{"class":3834,"line":3912},[3832,7507,7508],{"class":3838},"    \u002F\u002F Ці дані живуть тільки у компоненті\n",[3832,7510,7511],{"class":3834,"line":3922},[3832,7512,7513],{"class":3838},"    \u002F\u002F Вони зникають при розмонтуванні\n",[3832,7515,7516,7518],{"class":3834,"line":3932},[3832,7517,4911],{"class":3845},[3832,7519,4914],{"class":3849},[3832,7521,7522,7524,7526],{"class":3834,"line":3942},[3832,7523,4919],{"class":4834},[3832,7525,4630],{"class":3893},[3832,7527,4898],{"class":4834},[3832,7529,7530,7533,7536],{"class":3834,"line":3948},[3832,7531,7532],{"class":4834},"            \u003C",[3832,7534,7535],{"class":3893},"TextInput",[3832,7537,7538],{"class":3849}," \n",[3832,7540,7541,7544,7546,7548,7550,7552],{"class":3834,"line":3953},[3832,7542,7543],{"class":4840},"                value",[3832,7545,4844],{"class":3849},[3832,7547,4885],{"class":3889},[3832,7549,4998],{"class":3853},[3832,7551,4890],{"class":3889},[3832,7553,7538],{"class":3849},[3832,7555,7556,7559,7561,7563,7565],{"class":3834,"line":3959},[3832,7557,7558],{"class":4840},"                onChangeText",[3832,7560,4844],{"class":3849},[3832,7562,4885],{"class":3889},[3832,7564,7434],{"class":3853},[3832,7566,3945],{"class":3889},[3832,7568,7569,7572,7574],{"class":3834,"line":3969},[3832,7570,7571],{"class":4840},"                placeholder",[3832,7573,4844],{"class":3849},[3832,7575,7576],{"class":3869},"\"Назва поїздки\"\n",[3832,7578,7579],{"class":3834,"line":3986},[3832,7580,7581],{"class":4834},"            \u002F>\n",[3832,7583,7584,7587,7590],{"class":3834,"line":4000},[3832,7585,7586],{"class":3889},"            {",[3832,7588,7589],{"class":3838},"\u002F* ... інші поля *\u002F",[3832,7591,3945],{"class":3889},[3832,7593,7594,7597,7599],{"class":3834,"line":4020},[3832,7595,7596],{"class":4834},"        \u003C\u002F",[3832,7598,4630],{"class":3893},[3832,7600,4898],{"class":4834},[3832,7602,7603],{"class":3834,"line":4025},[3832,7604,5018],{"class":3849},[3832,7606,7607],{"class":3834,"line":4030},[3832,7608,3945],{"class":3849},[3801,7610,7400],{},[3801,7612,7400],{},[3801,7614,7615],{},[3770,7616,7617],{},"Ключові характеристики клієнтського стану:",[3746,7619,7620,7627,7633,7639,7645],{},[3749,7621,7622,7623,7626],{},"✅ ",[3770,7624,7625],{},"Синхронний доступ:"," дані доступні миттєво, без затримок",[3749,7628,7622,7629,7632],{},[3770,7630,7631],{},"Повний контроль:"," тільки ваш код може змінити ці дані",[3749,7634,7622,7635,7638],{},[3770,7636,7637],{},"Не застаріває:"," якщо користувач встановив темну тему, вона залишається темною",[3749,7640,7622,7641,7644],{},[3770,7642,7643],{},"Локальність:"," дані зникають при видаленні застосунку",[3749,7646,7647,7648,7651,7652,3857,7654,3857,7656],{},"🛠️ ",[3770,7649,7650],{},"Інструменти:"," ",[3829,7653,3854],{},[3829,7655,7440],{},[3829,7657,7658],{},"useReducer",[3809,7660,7662],{"id":7661},"що-таке-серверний-стан","Що таке серверний стан?",[3801,7664,7665,4307,7667,7669,7670,7673],{},[3770,7666,6822],{},[3817,7668,6805],{},") — це дані, ",[3770,7671,7672],{},"джерело істини яких знаходиться на віддаленому сервері",". Ваш застосунок зберігає лише тимчасову копію (кеш) цих даних.",[6852,7675,7677],{"id":7676},"практичні-приклади-серверного-стану","Практичні приклади серверного стану",[6860,7679,7680],{},[3822,7681,7684],{"className":3824,"code":7682,"filename":7683,"language":3826,"meta":3827,"style":3827},"\u002F\u002F Ці дані живуть на сервері в PostgreSQL\n\u002F\u002F Ваш застосунок отримує лише копію\ninterface Trip {\n    id: string\n    title: string\n    region: string\n    startDate: string\n    createdBy: string  \u002F\u002F Інший користувач міг створити\n    updatedAt: string  \u002F\u002F Міг змінити хтось інший\n}\n\n\u002F\u002F Проблема: між запитами дані могли змінитися!\nconst trips1 = await fetch('\u002Fapi\u002Ftrips')  \u002F\u002F 10 поїздок\n\u002F\u002F ... користувач згортає застосунок на 5 хвилин\nconst trips2 = await fetch('\u002Fapi\u002Ftrips')  \u002F\u002F тепер 12 поїздок?\n","Список поїздок з бази даних",[3829,7685,7686,7691,7696,7704,7712,7720,7728,7736,7748,7760,7764,7768,7773,7797,7802],{"__ignoreMap":3827},[3832,7687,7688],{"class":3834,"line":3835},[3832,7689,7690],{"class":3838},"\u002F\u002F Ці дані живуть на сервері в PostgreSQL\n",[3832,7692,7693],{"class":3834,"line":3842},[3832,7694,7695],{"class":3838},"\u002F\u002F Ваш застосунок отримує лише копію\n",[3832,7697,7698,7700,7702],{"class":3834,"line":3873},[3832,7699,3890],{"class":3889},[3832,7701,3894],{"class":3893},[3832,7703,3897],{"class":3849},[3832,7705,7706,7708,7710],{"class":3834,"line":3880},[3832,7707,3903],{"class":3853},[3832,7709,3906],{"class":3849},[3832,7711,3909],{"class":3893},[3832,7713,7714,7716,7718],{"class":3834,"line":3886},[3832,7715,3915],{"class":3853},[3832,7717,3906],{"class":3849},[3832,7719,3909],{"class":3893},[3832,7721,7722,7724,7726],{"class":3834,"line":3900},[3832,7723,3925],{"class":3853},[3832,7725,3906],{"class":3849},[3832,7727,3909],{"class":3893},[3832,7729,7730,7732,7734],{"class":3834,"line":3912},[3832,7731,3935],{"class":3853},[3832,7733,3906],{"class":3849},[3832,7735,3909],{"class":3893},[3832,7737,7738,7741,7743,7745],{"class":3834,"line":3922},[3832,7739,7740],{"class":3853},"    createdBy",[3832,7742,3906],{"class":3849},[3832,7744,4008],{"class":3893},[3832,7746,7747],{"class":3838},"  \u002F\u002F Інший користувач міг створити\n",[3832,7749,7750,7753,7755,7757],{"class":3834,"line":3932},[3832,7751,7752],{"class":3853},"    updatedAt",[3832,7754,3906],{"class":3849},[3832,7756,4008],{"class":3893},[3832,7758,7759],{"class":3838},"  \u002F\u002F Міг змінити хтось інший\n",[3832,7761,7762],{"class":3834,"line":3942},[3832,7763,3945],{"class":3849},[3832,7765,7766],{"class":3834,"line":3948},[3832,7767,3877],{"emptyLinePlaceholder":3876},[3832,7769,7770],{"class":3834,"line":3953},[3832,7771,7772],{"class":3838},"\u002F\u002F Проблема: між запитами дані могли змінитися!\n",[3832,7774,7775,7777,7780,7782,7784,7786,7788,7791,7794],{"class":3834,"line":3959},[3832,7776,4039],{"class":3889},[3832,7778,7779],{"class":4042}," trips1",[3832,7781,4114],{"class":3849},[3832,7783,4156],{"class":3845},[3832,7785,4159],{"class":4117},[3832,7787,4162],{"class":3849},[3832,7789,7790],{"class":3869},"'\u002Fapi\u002Ftrips'",[3832,7792,7793],{"class":3849},")  ",[3832,7795,7796],{"class":3838},"\u002F\u002F 10 поїздок\n",[3832,7798,7799],{"class":3834,"line":3969},[3832,7800,7801],{"class":3838},"\u002F\u002F ... користувач згортає застосунок на 5 хвилин\n",[3832,7803,7804,7806,7809,7811,7813,7815,7817,7819,7821],{"class":3834,"line":3986},[3832,7805,4039],{"class":3889},[3832,7807,7808],{"class":4042}," trips2",[3832,7810,4114],{"class":3849},[3832,7812,4156],{"class":3845},[3832,7814,4159],{"class":4117},[3832,7816,4162],{"class":3849},[3832,7818,7790],{"class":3869},[3832,7820,7793],{"class":3849},[3832,7822,7823],{"class":3838},"\u002F\u002F тепер 12 поїздок?\n",[3822,7825,7828],{"className":3824,"code":7826,"filename":7827,"language":3826,"meta":3827,"style":3827},"\u002F\u002F Дані профілю можуть змінитися через:\n\u002F\u002F - Веб-версію застосунку\n\u002F\u002F - Адмін-панель\n\u002F\u002F - Інший мобільний пристрій користувача\ninterface UserProfile {\n    id: string\n    name: string\n    email: string\n    avatarUrl: string\n    subscriptionStatus: 'free' | 'premium'\n}\n\n\u002F\u002F Питання: скільки часу можна довіряти закешованим даним?\n","Профіль користувача",[3829,7829,7830,7835,7840,7845,7850,7859,7867,7876,7885,7894,7909,7913,7917],{"__ignoreMap":3827},[3832,7831,7832],{"class":3834,"line":3835},[3832,7833,7834],{"class":3838},"\u002F\u002F Дані профілю можуть змінитися через:\n",[3832,7836,7837],{"class":3834,"line":3842},[3832,7838,7839],{"class":3838},"\u002F\u002F - Веб-версію застосунку\n",[3832,7841,7842],{"class":3834,"line":3873},[3832,7843,7844],{"class":3838},"\u002F\u002F - Адмін-панель\n",[3832,7846,7847],{"class":3834,"line":3880},[3832,7848,7849],{"class":3838},"\u002F\u002F - Інший мобільний пристрій користувача\n",[3832,7851,7852,7854,7857],{"class":3834,"line":3886},[3832,7853,3890],{"class":3889},[3832,7855,7856],{"class":3893}," UserProfile",[3832,7858,3897],{"class":3849},[3832,7860,7861,7863,7865],{"class":3834,"line":3900},[3832,7862,3903],{"class":3853},[3832,7864,3906],{"class":3849},[3832,7866,3909],{"class":3893},[3832,7868,7869,7872,7874],{"class":3834,"line":3912},[3832,7870,7871],{"class":3853},"    name",[3832,7873,3906],{"class":3849},[3832,7875,3909],{"class":3893},[3832,7877,7878,7881,7883],{"class":3834,"line":3922},[3832,7879,7880],{"class":3853},"    email",[3832,7882,3906],{"class":3849},[3832,7884,3909],{"class":3893},[3832,7886,7887,7890,7892],{"class":3834,"line":3932},[3832,7888,7889],{"class":3853},"    avatarUrl",[3832,7891,3906],{"class":3849},[3832,7893,3909],{"class":3893},[3832,7895,7896,7899,7901,7904,7906],{"class":3834,"line":3942},[3832,7897,7898],{"class":3853},"    subscriptionStatus",[3832,7900,3906],{"class":3849},[3832,7902,7903],{"class":3869},"'free'",[3832,7905,4011],{"class":3849},[3832,7907,7908],{"class":3869},"'premium'\n",[3832,7910,7911],{"class":3834,"line":3948},[3832,7912,3945],{"class":3849},[3832,7914,7915],{"class":3834,"line":3953},[3832,7916,3877],{"emptyLinePlaceholder":3876},[3832,7918,7919],{"class":3834,"line":3959},[3832,7920,7921],{"class":3838},"\u002F\u002F Питання: скільки часу можна довіряти закешованим даним?\n",[3801,7923,7400],{},[3822,7925,7928],{"className":3824,"code":7926,"filename":7927,"language":3826,"meta":3827,"style":3827},"\u002F\u002F Сценарій 1: Користувач відкрив застосунок\nconst profile = await fetchProfile()  \n\u002F\u002F { subscriptionStatus: 'free' }\n\n\u002F\u002F Користувач переходить на сайт і купує Premium\n\n\u002F\u002F Сценарій 2: Користувач повертається в застосунок\n\u002F\u002F Застосунок показує старі дані з кешу!\nconsole.log(profile.subscriptionStatus)  \u002F\u002F 'free' ❌ ЗАСТАРІЛО!\n\n\u002F\u002F Правильно: перезавантажити дані\nconst freshProfile = await fetchProfile()\n\u002F\u002F { subscriptionStatus: 'premium' } ✅\n","Реальний приклад: застарілі дані",[3829,7929,7930,7935,7952,7957,7961,7966,7970,7975,7980,8005,8009,8014,8029],{"__ignoreMap":3827},[3832,7931,7932],{"class":3834,"line":3835},[3832,7933,7934],{"class":3838},"\u002F\u002F Сценарій 1: Користувач відкрив застосунок\n",[3832,7936,7937,7939,7942,7944,7946,7949],{"class":3834,"line":3842},[3832,7938,4039],{"class":3889},[3832,7940,7941],{"class":4042}," profile",[3832,7943,4114],{"class":3849},[3832,7945,4156],{"class":3845},[3832,7947,7948],{"class":4117}," fetchProfile",[3832,7950,7951],{"class":3849},"()  \n",[3832,7953,7954],{"class":3834,"line":3873},[3832,7955,7956],{"class":3838},"\u002F\u002F { subscriptionStatus: 'free' }\n",[3832,7958,7959],{"class":3834,"line":3880},[3832,7960,3877],{"emptyLinePlaceholder":3876},[3832,7962,7963],{"class":3834,"line":3886},[3832,7964,7965],{"class":3838},"\u002F\u002F Користувач переходить на сайт і купує Premium\n",[3832,7967,7968],{"class":3834,"line":3900},[3832,7969,3877],{"emptyLinePlaceholder":3876},[3832,7971,7972],{"class":3834,"line":3912},[3832,7973,7974],{"class":3838},"\u002F\u002F Сценарій 2: Користувач повертається в застосунок\n",[3832,7976,7977],{"class":3834,"line":3922},[3832,7978,7979],{"class":3838},"\u002F\u002F Застосунок показує старі дані з кешу!\n",[3832,7981,7982,7985,7987,7990,7992,7995,7997,8000,8002],{"class":3834,"line":3932},[3832,7983,7984],{"class":3853},"console",[3832,7986,4183],{"class":3849},[3832,7988,7989],{"class":4117},"log",[3832,7991,4162],{"class":3849},[3832,7993,7994],{"class":3853},"profile",[3832,7996,4183],{"class":3849},[3832,7998,7999],{"class":3853},"subscriptionStatus",[3832,8001,7793],{"class":3849},[3832,8003,8004],{"class":3838},"\u002F\u002F 'free' ❌ ЗАСТАРІЛО!\n",[3832,8006,8007],{"class":3834,"line":3942},[3832,8008,3877],{"emptyLinePlaceholder":3876},[3832,8010,8011],{"class":3834,"line":3948},[3832,8012,8013],{"class":3838},"\u002F\u002F Правильно: перезавантажити дані\n",[3832,8015,8016,8018,8021,8023,8025,8027],{"class":3834,"line":3953},[3832,8017,4039],{"class":3889},[3832,8019,8020],{"class":4042}," freshProfile",[3832,8022,4114],{"class":3849},[3832,8024,4156],{"class":3845},[3832,8026,7948],{"class":4117},[3832,8028,4230],{"class":3849},[3832,8030,8031],{"class":3834,"line":3959},[3832,8032,8033],{"class":3838},"\u002F\u002F { subscriptionStatus: 'premium' } ✅\n",[3801,8035,7400],{},[3801,8037,7400],{},[3801,8039,8040],{},[3770,8041,8042],{},"Ключові характеристики серверного стану:",[3746,8044,8045,8052,8059,8066,8073,8080],{},[3749,8046,8047,8048,8051],{},"⏱️ ",[3770,8049,8050],{},"Асинхронний доступ:"," потрібен мережевий запит (затримка 100-500мс)",[3749,8053,8054,8055,8058],{},"🌐 ",[3770,8056,8057],{},"Розподілена зміна:"," дані можуть змінити інші користувачі або системи",[3749,8060,8061,8062,8065],{},"⚠️ ",[3770,8063,8064],{},"Може застаріти:"," локальна копія може не відповідати серверу",[3749,8067,8068,8069,8072],{},"🔄 ",[3770,8070,8071],{},"Потребує синхронізації:"," треба знати, коли перезавантажувати дані",[3749,8074,8075,8076,8079],{},"📦 ",[3770,8077,8078],{},"Вимагає кешування:"," для швидкості не робити запит кожного разу",[3749,8081,7647,8082,8084],{},[3770,8083,7650],{}," RTK Query, TanStack Query, SWR, Apollo Client",[3809,8086,8088],{"id":8087},"візуальне-порівняння-життєвий-цикл-даних","Візуальне порівняння: життєвий цикл даних",[8090,8091,8093],"plant-uml",{"alt":8092},"Порівняння життєвого циклу клієнтського та серверного стану",[3822,8094,8098],{"className":8095,"code":8096,"language":8097,"meta":3827,"style":3827},"language-plantuml shiki shiki-themes light-plus dark-plus dark-plus","@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\nskinparam defaultFontName \"Helvetica\"\n\npackage \"КЛІЄНТСЬКИЙ СТАН (локальний)\" {\n    [Користувач] as User1 #DBEAFE\n    [useState \u002F Redux Slice] as State #DCFCE7\n    \n    User1 --> State : Змінює тему\n    State --> User1 : Миттєво застосовує\n    \n    note right of State #FEF3C7\n        ✅ Завжди актуально\n        ✅ Синхронно\n        ✅ Повний контроль\n    end note\n}\n\npackage \"СЕРВЕРНИЙ СТАН (віддалений)\" {\n    [Користувач (мобілка)] as User2 #DBEAFE\n    [RTK Query Cache] as Cache #FED7AA\n    [API Server \u002F База даних] as Server #FECACA\n    [Інший користувач (веб)] as OtherUser #E0E7FF\n    \n    User2 --> Cache : 1. Читає дані\n    Cache --> Server : 2. Якщо немає\u002Fзастаріли\\nGET \u002Ftrips\n    Server --> Cache : 3. Повертає свіжі дані\n    Cache --> User2 : 4. Відображає\n    \n    OtherUser --> Server : Змінює дані\\nпоки застосунок\\nзгорнутий\n    \n    note right of Cache #FEF3C7\n        ⚠️ Може застаріти\n        ⏱️ Асинхронно\n        🔄 Потребує синхронізації\n    end note\n}\n\n@enduml\n","plantuml",[3829,8099,8100,8105,8110,8115,8120,8124,8129,8134,8139,8143,8148,8153,8157,8162,8167,8172,8177,8182,8186,8190,8195,8200,8205,8210,8215,8219,8224,8229,8234,8239,8243,8248,8252,8257,8262,8267,8272,8276,8280,8284],{"__ignoreMap":3827},[3832,8101,8102],{"class":3834,"line":3835},[3832,8103,8104],{},"@startuml\n",[3832,8106,8107],{"class":3834,"line":3842},[3832,8108,8109],{},"skinparam style plain\n",[3832,8111,8112],{"class":3834,"line":3873},[3832,8113,8114],{},"skinparam backgroundColor #ffffff\n",[3832,8116,8117],{"class":3834,"line":3880},[3832,8118,8119],{},"skinparam defaultFontName \"Helvetica\"\n",[3832,8121,8122],{"class":3834,"line":3886},[3832,8123,3877],{"emptyLinePlaceholder":3876},[3832,8125,8126],{"class":3834,"line":3900},[3832,8127,8128],{},"package \"КЛІЄНТСЬКИЙ СТАН (локальний)\" {\n",[3832,8130,8131],{"class":3834,"line":3912},[3832,8132,8133],{},"    [Користувач] as User1 #DBEAFE\n",[3832,8135,8136],{"class":3834,"line":3922},[3832,8137,8138],{},"    [useState \u002F Redux Slice] as State #DCFCE7\n",[3832,8140,8141],{"class":3834,"line":3932},[3832,8142,4724],{},[3832,8144,8145],{"class":3834,"line":3942},[3832,8146,8147],{},"    User1 --> State : Змінює тему\n",[3832,8149,8150],{"class":3834,"line":3948},[3832,8151,8152],{},"    State --> User1 : Миттєво застосовує\n",[3832,8154,8155],{"class":3834,"line":3953},[3832,8156,4724],{},[3832,8158,8159],{"class":3834,"line":3959},[3832,8160,8161],{},"    note right of State #FEF3C7\n",[3832,8163,8164],{"class":3834,"line":3969},[3832,8165,8166],{},"        ✅ Завжди актуально\n",[3832,8168,8169],{"class":3834,"line":3986},[3832,8170,8171],{},"        ✅ Синхронно\n",[3832,8173,8174],{"class":3834,"line":4000},[3832,8175,8176],{},"        ✅ Повний контроль\n",[3832,8178,8179],{"class":3834,"line":4020},[3832,8180,8181],{},"    end note\n",[3832,8183,8184],{"class":3834,"line":4025},[3832,8185,3945],{},[3832,8187,8188],{"class":3834,"line":4030},[3832,8189,3877],{"emptyLinePlaceholder":3876},[3832,8191,8192],{"class":3834,"line":4036},[3832,8193,8194],{},"package \"СЕРВЕРНИЙ СТАН (віддалений)\" {\n",[3832,8196,8197],{"class":3834,"line":4054},[3832,8198,8199],{},"    [Користувач (мобілка)] as User2 #DBEAFE\n",[3832,8201,8202],{"class":3834,"line":4063},[3832,8203,8204],{},"    [RTK Query Cache] as Cache #FED7AA\n",[3832,8206,8207],{"class":3834,"line":4075},[3832,8208,8209],{},"    [API Server \u002F База даних] as Server #FECACA\n",[3832,8211,8212],{"class":3834,"line":4086},[3832,8213,8214],{},"    [Інший користувач (веб)] as OtherUser #E0E7FF\n",[3832,8216,8217],{"class":3834,"line":4091},[3832,8218,4724],{},[3832,8220,8221],{"class":3834,"line":4096},[3832,8222,8223],{},"    User2 --> Cache : 1. Читає дані\n",[3832,8225,8226],{"class":3834,"line":4102},[3832,8227,8228],{},"    Cache --> Server : 2. Якщо немає\u002Fзастаріли\\nGET \u002Ftrips\n",[3832,8230,8231],{"class":3834,"line":4123},[3832,8232,8233],{},"    Server --> Cache : 3. Повертає свіжі дані\n",[3832,8235,8236],{"class":3834,"line":4131},[3832,8237,8238],{},"    Cache --> User2 : 4. Відображає\n",[3832,8240,8241],{"class":3834,"line":4145},[3832,8242,4724],{},[3832,8244,8245],{"class":3834,"line":4171},[3832,8246,8247],{},"    OtherUser --> Server : Змінює дані\\nпоки застосунок\\nзгорнутий\n",[3832,8249,8250],{"class":3834,"line":4192},[3832,8251,4724],{},[3832,8253,8254],{"class":3834,"line":4211},[3832,8255,8256],{},"    note right of Cache #FEF3C7\n",[3832,8258,8259],{"class":3834,"line":4217},[3832,8260,8261],{},"        ⚠️ Може застаріти\n",[3832,8263,8264],{"class":3834,"line":4233},[3832,8265,8266],{},"        ⏱️ Асинхронно\n",[3832,8268,8269],{"class":3834,"line":4239},[3832,8270,8271],{},"        🔄 Потребує синхронізації\n",[3832,8273,8274],{"class":3834,"line":4244},[3832,8275,8181],{},[3832,8277,8278],{"class":3834,"line":4249},[3832,8279,3945],{},[3832,8281,8282],{"class":3834,"line":4255},[3832,8283,3877],{"emptyLinePlaceholder":3876},[3832,8285,8286],{"class":3834,"line":4270},[3832,8287,8288],{},"@enduml\n",[3809,8290,8292],{"id":8291},"практичний-сценарій-чому-важлива-ця-різниця","Практичний сценарій: Чому важлива ця різниця?",[3801,8294,8295],{},"Уявіть застосунок для планування подорожей. Давайте подивимось, як обидва типи стану працюють разом:",[3822,8297,8299],{"className":4592,"code":8298,"language":4594,"meta":3827,"style":3827},"\u002F\u002F src\u002Fscreens\u002FTripDetailsScreen.tsx\nimport { useSelector } from 'react-redux'\nimport { useGetTripByIdQuery } from '@\u002Fservices\u002FtripsApi'\n\nfunction TripDetailsScreen({ tripId }) {\n    \u002F\u002F 1. КЛІЄНТСЬКИЙ СТАН: налаштування теми (з Redux slice)\n    const theme = useSelector((state) => state.theme.mode)\n    \n    \u002F\u002F 2. СЕРВЕРНИЙ СТАН: деталі поїздки (з RTK Query)\n    const { data: trip, isLoading } = useGetTripByIdQuery(tripId)\n    \n    if (isLoading) return \u003CActivityIndicator \u002F>\n    \n    return (\n        \u003CView style={{ backgroundColor: theme === 'dark' ? '#000' : '#fff' }}>\n            {\u002F* Тема (клієнтський стан) — застосовується миттєво *\u002F}\n            \n            \u003CText>{trip.title}\u003C\u002FText>\n            {\u002F* Деталі поїздки (серверний стан) — можуть оновитись при refetch *\u002F}\n        \u003C\u002FView>\n    )\n}\n",[3829,8300,8301,8306,8320,8335,8339,8354,8359,8391,8395,8400,8427,8431,8449,8453,8459,8505,8514,8519,8543,8552,8560,8564],{"__ignoreMap":3827},[3832,8302,8303],{"class":3834,"line":3835},[3832,8304,8305],{"class":3838},"\u002F\u002F src\u002Fscreens\u002FTripDetailsScreen.tsx\n",[3832,8307,8308,8310,8312,8314,8316,8318],{"class":3834,"line":3842},[3832,8309,3846],{"class":3845},[3832,8311,3850],{"class":3849},[3832,8313,4666],{"class":3853},[3832,8315,3863],{"class":3849},[3832,8317,3866],{"class":3845},[3832,8319,4673],{"class":3869},[3832,8321,8322,8324,8326,8329,8331,8333],{"class":3834,"line":3873},[3832,8323,3846],{"class":3845},[3832,8325,3850],{"class":3849},[3832,8327,8328],{"class":3853},"useGetTripByIdQuery",[3832,8330,3863],{"class":3849},[3832,8332,3866],{"class":3845},[3832,8334,6537],{"class":3869},[3832,8336,8337],{"class":3834,"line":3880},[3832,8338,3877],{"emptyLinePlaceholder":3876},[3832,8340,8341,8343,8346,8348,8351],{"class":3834,"line":3886},[3832,8342,7416],{"class":3889},[3832,8344,8345],{"class":4117}," TripDetailsScreen",[3832,8347,4976],{"class":3849},[3832,8349,8350],{"class":3853},"tripId",[3832,8352,8353],{"class":3849}," }) {\n",[3832,8355,8356],{"class":3834,"line":3900},[3832,8357,8358],{"class":3838},"    \u002F\u002F 1. КЛІЄНТСЬКИЙ СТАН: налаштування теми (з Redux slice)\n",[3832,8360,8361,8363,8366,8368,8370,8372,8374,8376,8378,8380,8382,8385,8387,8389],{"class":3834,"line":3912},[3832,8362,4710],{"class":3889},[3832,8364,8365],{"class":4042}," theme",[3832,8367,4114],{"class":3849},[3832,8369,4666],{"class":4117},[3832,8371,4753],{"class":3849},[3832,8373,4354],{"class":3853},[3832,8375,4313],{"class":3849},[3832,8377,4140],{"class":3889},[3832,8379,4762],{"class":3853},[3832,8381,4183],{"class":3849},[3832,8383,8384],{"class":3853},"theme",[3832,8386,4183],{"class":3849},[3832,8388,7040],{"class":3853},[3832,8390,4168],{"class":3849},[3832,8392,8393],{"class":3834,"line":3922},[3832,8394,4724],{"class":3849},[3832,8396,8397],{"class":3834,"line":3932},[3832,8398,8399],{"class":3838},"    \u002F\u002F 2. СЕРВЕРНИЙ СТАН: деталі поїздки (з RTK Query)\n",[3832,8401,8402,8404,8406,8408,8410,8413,8415,8417,8419,8421,8423,8425],{"class":3834,"line":3942},[3832,8403,4710],{"class":3889},[3832,8405,3850],{"class":3849},[3832,8407,6565],{"class":3853},[3832,8409,3906],{"class":3849},[3832,8411,8412],{"class":4042},"trip",[3832,8414,3857],{"class":3849},[3832,8416,4371],{"class":4042},[3832,8418,4748],{"class":3849},[3832,8420,8328],{"class":4117},[3832,8422,4162],{"class":3849},[3832,8424,8350],{"class":3853},[3832,8426,4168],{"class":3849},[3832,8428,8429],{"class":3834,"line":3948},[3832,8430,4724],{"class":3849},[3832,8432,8433,8435,8437,8439,8441,8443,8445,8447],{"class":3834,"line":3953},[3832,8434,4821],{"class":3845},[3832,8436,4307],{"class":3849},[3832,8438,4371],{"class":3853},[3832,8440,4313],{"class":3849},[3832,8442,6600],{"class":3845},[3832,8444,4835],{"class":4834},[3832,8446,4645],{"class":3893},[3832,8448,4850],{"class":4834},[3832,8450,8451],{"class":3834,"line":3959},[3832,8452,4724],{"class":3849},[3832,8454,8455,8457],{"class":3834,"line":3969},[3832,8456,4911],{"class":3845},[3832,8458,4914],{"class":3849},[3832,8460,8461,8463,8465,8468,8470,8472,8475,8478,8480,8483,8486,8489,8492,8495,8498,8501,8503],{"class":3834,"line":3986},[3832,8462,4919],{"class":4834},[3832,8464,4630],{"class":3893},[3832,8466,8467],{"class":4840}," style",[3832,8469,4844],{"class":3849},[3832,8471,4885],{"class":3889},[3832,8473,8474],{"class":4947},"{ ",[3832,8476,8477],{"class":3853},"backgroundColor:",[3832,8479,8365],{"class":3853},[3832,8481,8482],{"class":3849}," ===",[3832,8484,8485],{"class":3869}," 'dark'",[3832,8487,8488],{"class":3849}," ?",[3832,8490,8491],{"class":3869}," '#000'",[3832,8493,8494],{"class":3849}," :",[3832,8496,8497],{"class":3869}," '#fff'",[3832,8499,8500],{"class":4947}," }",[3832,8502,4890],{"class":3889},[3832,8504,4898],{"class":4834},[3832,8506,8507,8509,8512],{"class":3834,"line":4000},[3832,8508,7586],{"class":3889},[3832,8510,8511],{"class":3838},"\u002F* Тема (клієнтський стан) — застосовується миттєво *\u002F",[3832,8513,3945],{"class":3889},[3832,8515,8516],{"class":3834,"line":4020},[3832,8517,8518],{"class":3849},"            \n",[3832,8520,8521,8523,8525,8527,8529,8531,8533,8535,8537,8539,8541],{"class":3834,"line":4025},[3832,8522,7532],{"class":4834},[3832,8524,4635],{"class":3893},[3832,8526,4879],{"class":4834},[3832,8528,4885],{"class":3889},[3832,8530,8412],{"class":3853},[3832,8532,4183],{"class":4947},[3832,8534,4998],{"class":3853},[3832,8536,4890],{"class":3889},[3832,8538,4893],{"class":4834},[3832,8540,4635],{"class":3893},[3832,8542,4898],{"class":4834},[3832,8544,8545,8547,8550],{"class":3834,"line":4030},[3832,8546,7586],{"class":3889},[3832,8548,8549],{"class":3838},"\u002F* Деталі поїздки (серверний стан) — можуть оновитись при refetch *\u002F",[3832,8551,3945],{"class":3889},[3832,8553,8554,8556,8558],{"class":3834,"line":4036},[3832,8555,7596],{"class":4834},[3832,8557,4630],{"class":3893},[3832,8559,4898],{"class":4834},[3832,8561,8562],{"class":3834,"line":4054},[3832,8563,5018],{"class":3849},[3832,8565,8566],{"class":3834,"line":4063},[3832,8567,3945],{"class":3849},[8569,8570,8571,8576,8597],"tip",{},[3801,8572,8573],{},[3770,8574,8575],{},"Правило великого пальця:",[3746,8577,8578,8590],{},[3749,8579,8580,8581,8584,8585,8587,8588],{},"Якщо дані живуть ",[3770,8582,8583],{},"тільки у вашому застосунку"," → ",[3829,8586,3854],{}," або ",[3829,8589,7440],{},[3749,8591,8592,8593,8596],{},"Якщо дані приходять ",[3770,8594,8595],{},"з віддаленого сервера"," → RTK Query (або інший інструмент серверного стану)",[3801,8598,8599],{},"Не намагайтеся зберігати серверні дані у звичайному Redux слайсі — ви витратите тижні на написання логіки, яку RTK Query робить автоматично!",[3809,8601,8603],{"id":8602},"порівняння-бібліотек-для-серверного-стану","Порівняння бібліотек для серверного стану",[3801,8605,8606],{},"Тепер, коли ми розуміємо природу серверного стану, давайте порівняємо інструменти для роботи з ним:",[8608,8609,8610,8640],"table",{},[8611,8612,8613],"thead",{},[8614,8615,8616,8621,8625,8630,8635],"tr",{},[8617,8618,8620],"th",{"align":8619},"left","Критерій",[8617,8622,8623],{"align":8619},[3770,8624,6131],{},[8617,8626,8627],{"align":8619},[3770,8628,8629],{},"TanStack Query",[8617,8631,8632],{"align":8619},[3770,8633,8634],{},"SWR",[8617,8636,8637],{"align":8619},[3770,8638,8639],{},"Apollo Client",[8641,8642,8643,8663,8682,8701,8722,8740,8757],"tbody",{},[8614,8644,8645,8651,8654,8657,8660],{},[8646,8647,8648],"td",{"align":8619},[3770,8649,8650],{},"Екосистема",[8646,8652,8653],{"align":8619},"Частина Redux Toolkit",[8646,8655,8656],{"align":8619},"Незалежна бібліотека",[8646,8658,8659],{"align":8619},"Від команди Vercel",[8646,8661,8662],{"align":8619},"Для GraphQL",[8614,8664,8665,8670,8673,8676,8679],{},[8646,8666,8667],{"align":8619},[3770,8668,8669],{},"Інтеграція з Redux",[8646,8671,8672],{"align":8619},"✅ Нативна (єдині DevTools)",[8646,8674,8675],{"align":8619},"⚠️ Окреме підключення",[8646,8677,8678],{"align":8619},"❌ Окреме дерево стану",[8646,8680,8681],{"align":8619},"❌ Окреме дерево",[8614,8683,8684,8689,8692,8695,8698],{},[8646,8685,8686],{"align":8619},[3770,8687,8688],{},"Розмір бандлу",[8646,8690,8691],{"align":8619},"~9KB (якщо Redux вже є)",[8646,8693,8694],{"align":8619},"~13KB",[8646,8696,8697],{"align":8619},"~5KB",[8646,8699,8700],{"align":8619},"~33KB",[8614,8702,8703,8708,8711,8714,8716],{},[8646,8704,8705],{"align":8619},[3770,8706,8707],{},"Інвалідація кешу",[8646,8709,8710],{"align":8619},"Теги (декларативно)",[8646,8712,8713],{"align":8619},"Ключі (імперативно)",[8646,8715,8713],{"align":8619},[8646,8717,8718,8721],{"align":8619},[3829,8719,8720],{},"__typename"," (авто)",[8614,8723,8724,8729,8732,8735,8737],{},[8646,8725,8726],{"align":8619},[3770,8727,8728],{},"Генерація хуків",[8646,8730,8731],{"align":8619},"✅ Автоматична",[8646,8733,8734],{"align":8619},"❌ Ручна",[8646,8736,8734],{"align":8619},[8646,8738,8739],{"align":8619},"⚠️ З GraphQL схеми",[8614,8741,8742,8746,8749,8751,8754],{},[8646,8743,8744],{"align":8619},[3770,8745,2325],{},[8646,8747,8748],{"align":8619},"✅ Відмінна підтримка",[8646,8750,8748],{"align":8619},[8646,8752,8753],{"align":8619},"✅ Добра підтримка",[8646,8755,8756],{"align":8619},"✅ З кодогенерацією",[8614,8758,8759,8764,8767,8770,8773],{},[8646,8760,8761],{"align":8619},[3770,8762,8763],{},"Коли обирати",[8646,8765,8766],{"align":8619},"У вас вже є Redux",[8646,8768,8769],{"align":8619},"Redux не потрібен",[8646,8771,8772],{"align":8619},"Простий REST API",[8646,8774,8775],{"align":8619},"Тільки GraphQL",[8777,8778,8779,8822],"accordion",{},[8780,8781,8784,8789,8803,8808,8819],"accordion-item",{"icon":8782,"label":8783},"i-lucide-help-circle","🤔 Чому обрати RTK Query, якщо є TanStack Query?",[3801,8785,8786],{},[3770,8787,8788],{},"RTK Query обирайте, якщо:",[3746,8790,8791,8794,8797,8800],{},[3749,8792,8793],{},"Ваш застосунок вже використовує Redux для клієнтського стану (налаштування, UI, авторизація)",[3749,8795,8796],{},"Ви хочете один інструмент для всього (Redux DevTools показує і клієнтський, і серверний стан)",[3749,8798,8799],{},"Вам потрібна декларативна система інвалідації через теги",[3749,8801,8802],{},"Ви цінуєте автоматичну генерацію типізованих хуків",[3801,8804,8805],{},[3770,8806,8807],{},"TanStack Query обирайте, якщо:",[3746,8809,8810,8813,8816],{},[3749,8811,8812],{},"У вас немає Redux і не планується (використовуєте Zustand, Jotai або Context API)",[3749,8814,8815],{},"Вам потрібна більша гнучкість у налаштуванні кешування",[3749,8817,8818],{},"Ви хочете мінімальний розмір бандлу",[3801,8820,8821],{},"В контексті цього курсу ми вивчаємо RTK Query, бо він ідеально інтегрується з Redux екосистемою, яку ми вже опанували у попередніх розділах.",[8780,8823,8825,8835,8841],{"icon":8782,"label":8824},"🤔 А що якщо мій бекенд на GraphQL?",[3801,8826,8827,8828,8831,8832,8834],{},"Якщо ваш сервер використовує ",[3770,8829,8830],{},"GraphQL"," замість REST API, найкращим вибором буде ",[3770,8833,8639],{},". Він має вбудовану підтримку GraphQL запитів, автоматичну нормалізацію кешу та інтеграцію з GraphQL схемою.",[3801,8836,8837,8838,4304],{},"Проте RTK Query теж може працювати з GraphQL! Потрібно лише налаштувати кастомний ",[3829,8839,8840],{},"baseQuery",[3822,8842,8844],{"className":3824,"code":8843,"language":3826,"meta":3827,"style":3827},"import { createApi, fetchBaseQuery } from '@reduxjs\u002Ftoolkit\u002Fquery\u002Freact'\n\nexport const graphqlApi = createApi({\n    baseQuery: fetchBaseQuery({\n        baseUrl: 'https:\u002F\u002Fapi.example.com\u002Fgraphql',\n        prepareHeaders: (headers) => {\n            headers.set('Content-Type', 'application\u002Fjson')\n            return headers\n        },\n    }),\n    endpoints: (builder) => ({\n        getTrips: builder.query({\n            query: () => ({\n                body: JSON.stringify({\n                    query: `\n                        query GetTrips {\n                            trips {\n                                id\n                                title\n                                region\n                            }\n                        }\n                    `,\n                }),\n                method: 'POST',\n            }),\n        }),\n    }),\n})\n",[3829,8845,8846,8864,8868,8883,8891,8901,8919,8940,8948,8952,8956,8972,8984,8996,9008,9016,9021,9026,9031,9036,9041,9046,9051,9058,9063,9071,9075,9079,9083],{"__ignoreMap":3827},[3832,8847,8848,8850,8852,8854,8856,8858,8860,8862],{"class":3834,"line":3835},[3832,8849,3846],{"class":3845},[3832,8851,3850],{"class":3849},[3832,8853,6153],{"class":3853},[3832,8855,3857],{"class":3849},[3832,8857,6158],{"class":3853},[3832,8859,3863],{"class":3849},[3832,8861,3866],{"class":3845},[3832,8863,6165],{"class":3869},[3832,8865,8866],{"class":3834,"line":3842},[3832,8867,3877],{"emptyLinePlaceholder":3876},[3832,8869,8870,8872,8874,8877,8879,8881],{"class":3834,"line":3873},[3832,8871,4105],{"class":3845},[3832,8873,4108],{"class":3889},[3832,8875,8876],{"class":4042}," graphqlApi",[3832,8878,4114],{"class":3849},[3832,8880,6153],{"class":4117},[3832,8882,4267],{"class":3849},[3832,8884,8885,8887,8889],{"class":3834,"line":3880},[3832,8886,6252],{"class":3853},[3832,8888,6255],{"class":4117},[3832,8890,4267],{"class":3849},[3832,8892,8893,8896,8899],{"class":3834,"line":3886},[3832,8894,8895],{"class":3853},"        baseUrl:",[3832,8897,8898],{"class":3869}," 'https:\u002F\u002Fapi.example.com\u002Fgraphql'",[3832,8900,4072],{"class":3849},[3832,8902,8903,8906,8908,8910,8913,8915,8917],{"class":3834,"line":3900},[3832,8904,8905],{"class":4117},"        prepareHeaders",[3832,8907,4304],{"class":3853},[3832,8909,4307],{"class":3849},[3832,8911,8912],{"class":3853},"headers",[3832,8914,4313],{"class":3849},[3832,8916,4140],{"class":3889},[3832,8918,3897],{"class":3849},[3832,8920,8921,8924,8926,8929,8931,8933,8935,8938],{"class":3834,"line":3912},[3832,8922,8923],{"class":3853},"            headers",[3832,8925,4183],{"class":3849},[3832,8927,8928],{"class":4117},"set",[3832,8930,4162],{"class":3849},[3832,8932,5137],{"class":3869},[3832,8934,3857],{"class":3849},[3832,8936,8937],{"class":3869},"'application\u002Fjson'",[3832,8939,4168],{"class":3849},[3832,8941,8942,8945],{"class":3834,"line":3922},[3832,8943,8944],{"class":3845},"            return",[3832,8946,8947],{"class":3853}," headers\n",[3832,8949,8950],{"class":3834,"line":3932},[3832,8951,7069],{"class":3849},[3832,8953,8954],{"class":3834,"line":3942},[3832,8955,6475],{"class":3849},[3832,8957,8958,8960,8962,8964,8966,8968,8970],{"class":3834,"line":3948},[3832,8959,6288],{"class":4117},[3832,8961,4304],{"class":3853},[3832,8963,4307],{"class":3849},[3832,8965,4310],{"class":3853},[3832,8967,4313],{"class":3849},[3832,8969,4140],{"class":3889},[3832,8971,6301],{"class":3849},[3832,8973,8974,8976,8978,8980,8982],{"class":3834,"line":3953},[3832,8975,6311],{"class":3853},[3832,8977,6314],{"class":3853},[3832,8979,4183],{"class":3849},[3832,8981,6319],{"class":4117},[3832,8983,4267],{"class":3849},[3832,8985,8986,8988,8990,8992,8994],{"class":3834,"line":3959},[3832,8987,6337],{"class":4117},[3832,8989,4304],{"class":3853},[3832,8991,4137],{"class":3849},[3832,8993,4140],{"class":3889},[3832,8995,6301],{"class":3849},[3832,8997,8998,9000,9002,9004,9006],{"class":3834,"line":3969},[3832,8999,6442],{"class":3853},[3832,9001,5153],{"class":4042},[3832,9003,4183],{"class":3849},[3832,9005,5158],{"class":4117},[3832,9007,4267],{"class":3849},[3832,9009,9010,9013],{"class":3834,"line":3986},[3832,9011,9012],{"class":3853},"                    query:",[3832,9014,9015],{"class":3869}," `\n",[3832,9017,9018],{"class":3834,"line":4000},[3832,9019,9020],{"class":3869},"                        query GetTrips {\n",[3832,9022,9023],{"class":3834,"line":4020},[3832,9024,9025],{"class":3869},"                            trips {\n",[3832,9027,9028],{"class":3834,"line":4025},[3832,9029,9030],{"class":3869},"                                id\n",[3832,9032,9033],{"class":3834,"line":4030},[3832,9034,9035],{"class":3869},"                                title\n",[3832,9037,9038],{"class":3834,"line":4036},[3832,9039,9040],{"class":3869},"                                region\n",[3832,9042,9043],{"class":3834,"line":4054},[3832,9044,9045],{"class":3869},"                            }\n",[3832,9047,9048],{"class":3834,"line":4063},[3832,9049,9050],{"class":3869},"                        }\n",[3832,9052,9053,9056],{"class":3834,"line":4075},[3832,9054,9055],{"class":3869},"                    `",[3832,9057,4072],{"class":3849},[3832,9059,9060],{"class":3834,"line":4086},[3832,9061,9062],{"class":3849},"                }),\n",[3832,9064,9065,9067,9069],{"class":3834,"line":4091},[3832,9066,6433],{"class":3853},[3832,9068,5125],{"class":3869},[3832,9070,4072],{"class":3849},[3832,9072,9073],{"class":3834,"line":4096},[3832,9074,6452],{"class":3849},[3832,9076,9077],{"class":3834,"line":4102},[3832,9078,6367],{"class":3849},[3832,9080,9081],{"class":3834,"line":4123},[3832,9082,6475],{"class":3849},[3832,9084,9085],{"class":3834,"line":4131},[3832,9086,4566],{"class":3849},[3793,9088],{},[3796,9090,9092,9093],{"id":9091},"перші-кроки-налаштування-createapi","Перші кроки: Налаштування ",[3829,9094,6153],{},[3801,9096,9097],{},"Тепер, коли ми розуміємо проблему та її рішення, давайте створимо наш перший RTK Query API. Почнемо з найпростішої конфігурації та поступово додаватимемо функціональність.",[3809,9099,9101],{"id":9100},"крок-1-встановлення-залежностей","Крок 1: Встановлення залежностей",[3801,9103,9104],{},"Спочатку переконайтесь, що у вашому проєкті встановлено Redux Toolkit:",[5457,9106,9107,9130,9149],{},[5460,9108,9110],{"label":9109},"npm",[3822,9111,9115],{"className":9112,"code":9113,"language":9114,"meta":3827,"style":3827},"language-bash shiki shiki-themes light-plus dark-plus dark-plus","npm install @reduxjs\u002Ftoolkit react-redux\n","bash",[3829,9116,9117],{"__ignoreMap":3827},[3832,9118,9119,9121,9124,9127],{"class":3834,"line":3835},[3832,9120,9109],{"class":4117},[3832,9122,9123],{"class":3869}," install",[3832,9125,9126],{"class":3869}," @reduxjs\u002Ftoolkit",[3832,9128,9129],{"class":3869}," react-redux\n",[5460,9131,9133],{"label":9132},"yarn",[3822,9134,9136],{"className":9112,"code":9135,"language":9114,"meta":3827,"style":3827},"yarn add @reduxjs\u002Ftoolkit react-redux\n",[3829,9137,9138],{"__ignoreMap":3827},[3832,9139,9140,9142,9145,9147],{"class":3834,"line":3835},[3832,9141,9132],{"class":4117},[3832,9143,9144],{"class":3869}," add",[3832,9146,9126],{"class":3869},[3832,9148,9129],{"class":3869},[5460,9150,9152],{"label":9151},"pnpm",[3822,9153,9155],{"className":9112,"code":9154,"language":9114,"meta":3827,"style":3827},"pnpm add @reduxjs\u002Ftoolkit react-redux\n",[3829,9156,9157],{"__ignoreMap":3827},[3832,9158,9159,9161,9163,9165],{"class":3834,"line":3835},[3832,9160,9151],{"class":4117},[3832,9162,9144],{"class":3869},[3832,9164,9126],{"class":3869},[3832,9166,9129],{"class":3869},[6795,9168,9169,9172,9173,9176],{},[3770,9170,9171],{},"Важливо:"," RTK Query входить до складу ",[3829,9174,9175],{},"@reduxjs\u002Ftoolkit"," — не потрібно встановлювати окремий пакет! Якщо ви вже використовуєте Redux Toolkit у своєму проєкті, RTK Query вже доступний.",[3809,9178,9180],{"id":9179},"крок-2-найпростіша-конфігурація","Крок 2: Найпростіша конфігурація",[3801,9182,9183],{},"Створимо мінімальний API для роботи з публічним тестовим сервером:",[3822,9185,9187],{"className":3824,"code":9186,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fservices\u002Fapi.ts\nimport { createApi, fetchBaseQuery } from '@reduxjs\u002Ftoolkit\u002Fquery\u002Freact'\n\n\u002F\u002F Визначаємо структуру даних\ninterface Post {\n    id: number\n    title: string\n    body: string\n}\n\n\u002F\u002F Створюємо API\nexport const api = createApi({\n    \u002F\u002F Назва слайса у Redux store\n    reducerPath: 'api',\n    \n    \u002F\u002F Базова конфігурація запитів\n    baseQuery: fetchBaseQuery({ \n        baseUrl: 'https:\u002F\u002Fjsonplaceholder.typicode.com' \n    }),\n    \n    \u002F\u002F Описуємо ендпоінти\n    endpoints: (builder) => ({\n        \u002F\u002F Один простий GET-запит\n        getPosts: builder.query\u003CPost[], void>({\n            query: () => '\u002Fposts',\n        }),\n    }),\n})\n\n\u002F\u002F RTK Query автоматично створює хук!\nexport const { useGetPostsQuery } = api\n",[3829,9188,9189,9194,9212,9216,9221,9230,9239,9247,9256,9260,9264,9269,9284,9289,9298,9302,9307,9316,9325,9329,9333,9338,9354,9359,9381,9396,9400,9404,9408,9412,9417],{"__ignoreMap":3827},[3832,9190,9191],{"class":3834,"line":3835},[3832,9192,9193],{"class":3838},"\u002F\u002F src\u002Fservices\u002Fapi.ts\n",[3832,9195,9196,9198,9200,9202,9204,9206,9208,9210],{"class":3834,"line":3842},[3832,9197,3846],{"class":3845},[3832,9199,3850],{"class":3849},[3832,9201,6153],{"class":3853},[3832,9203,3857],{"class":3849},[3832,9205,6158],{"class":3853},[3832,9207,3863],{"class":3849},[3832,9209,3866],{"class":3845},[3832,9211,6165],{"class":3869},[3832,9213,9214],{"class":3834,"line":3873},[3832,9215,3877],{"emptyLinePlaceholder":3876},[3832,9217,9218],{"class":3834,"line":3880},[3832,9219,9220],{"class":3838},"\u002F\u002F Визначаємо структуру даних\n",[3832,9222,9223,9225,9228],{"class":3834,"line":3886},[3832,9224,3890],{"class":3889},[3832,9226,9227],{"class":3893}," Post",[3832,9229,3897],{"class":3849},[3832,9231,9232,9234,9236],{"class":3834,"line":3900},[3832,9233,3903],{"class":3853},[3832,9235,3906],{"class":3849},[3832,9237,9238],{"class":3893},"number\n",[3832,9240,9241,9243,9245],{"class":3834,"line":3912},[3832,9242,3915],{"class":3853},[3832,9244,3906],{"class":3849},[3832,9246,3909],{"class":3893},[3832,9248,9249,9252,9254],{"class":3834,"line":3922},[3832,9250,9251],{"class":3853},"    body",[3832,9253,3906],{"class":3849},[3832,9255,3909],{"class":3893},[3832,9257,9258],{"class":3834,"line":3932},[3832,9259,3945],{"class":3849},[3832,9261,9262],{"class":3834,"line":3942},[3832,9263,3877],{"emptyLinePlaceholder":3876},[3832,9265,9266],{"class":3834,"line":3948},[3832,9267,9268],{"class":3838},"\u002F\u002F Створюємо API\n",[3832,9270,9271,9273,9275,9278,9280,9282],{"class":3834,"line":3953},[3832,9272,4105],{"class":3845},[3832,9274,4108],{"class":3889},[3832,9276,9277],{"class":4042}," api",[3832,9279,4114],{"class":3849},[3832,9281,6153],{"class":4117},[3832,9283,4267],{"class":3849},[3832,9285,9286],{"class":3834,"line":3959},[3832,9287,9288],{"class":3838},"    \u002F\u002F Назва слайса у Redux store\n",[3832,9290,9291,9293,9296],{"class":3834,"line":3969},[3832,9292,6242],{"class":3853},[3832,9294,9295],{"class":3869}," 'api'",[3832,9297,4072],{"class":3849},[3832,9299,9300],{"class":3834,"line":3986},[3832,9301,4724],{"class":3849},[3832,9303,9304],{"class":3834,"line":4000},[3832,9305,9306],{"class":3838},"    \u002F\u002F Базова конфігурація запитів\n",[3832,9308,9309,9311,9313],{"class":3834,"line":4020},[3832,9310,6252],{"class":3853},[3832,9312,6255],{"class":4117},[3832,9314,9315],{"class":3849},"({ \n",[3832,9317,9318,9320,9323],{"class":3834,"line":4025},[3832,9319,8895],{"class":3853},[3832,9321,9322],{"class":3869}," 'https:\u002F\u002Fjsonplaceholder.typicode.com'",[3832,9324,7538],{"class":3849},[3832,9326,9327],{"class":3834,"line":4030},[3832,9328,6475],{"class":3849},[3832,9330,9331],{"class":3834,"line":4036},[3832,9332,4724],{"class":3849},[3832,9334,9335],{"class":3834,"line":4054},[3832,9336,9337],{"class":3838},"    \u002F\u002F Описуємо ендпоінти\n",[3832,9339,9340,9342,9344,9346,9348,9350,9352],{"class":3834,"line":4063},[3832,9341,6288],{"class":4117},[3832,9343,4304],{"class":3853},[3832,9345,4307],{"class":3849},[3832,9347,4310],{"class":3853},[3832,9349,4313],{"class":3849},[3832,9351,4140],{"class":3889},[3832,9353,6301],{"class":3849},[3832,9355,9356],{"class":3834,"line":4075},[3832,9357,9358],{"class":3838},"        \u002F\u002F Один простий GET-запит\n",[3832,9360,9361,9364,9366,9368,9370,9372,9375,9377,9379],{"class":3834,"line":4086},[3832,9362,9363],{"class":3853},"        getPosts:",[3832,9365,6314],{"class":3853},[3832,9367,4183],{"class":3849},[3832,9369,6319],{"class":4117},[3832,9371,5084],{"class":3849},[3832,9373,9374],{"class":3893},"Post",[3832,9376,6326],{"class":3849},[3832,9378,6329],{"class":3893},[3832,9380,6332],{"class":3849},[3832,9382,9383,9385,9387,9389,9391,9394],{"class":3834,"line":4091},[3832,9384,6337],{"class":4117},[3832,9386,4304],{"class":3853},[3832,9388,4137],{"class":3849},[3832,9390,4140],{"class":3889},[3832,9392,9393],{"class":3869}," '\u002Fposts'",[3832,9395,4072],{"class":3849},[3832,9397,9398],{"class":3834,"line":4096},[3832,9399,6367],{"class":3849},[3832,9401,9402],{"class":3834,"line":4102},[3832,9403,6475],{"class":3849},[3832,9405,9406],{"class":3834,"line":4123},[3832,9407,4566],{"class":3849},[3832,9409,9410],{"class":3834,"line":4131},[3832,9411,3877],{"emptyLinePlaceholder":3876},[3832,9413,9414],{"class":3834,"line":4145},[3832,9415,9416],{"class":3838},"\u002F\u002F RTK Query автоматично створює хук!\n",[3832,9418,9419,9421,9423,9425,9428,9430],{"class":3834,"line":4171},[3832,9420,4105],{"class":3845},[3832,9422,4108],{"class":3889},[3832,9424,3850],{"class":3849},[3832,9426,9427],{"class":4042},"useGetPostsQuery",[3832,9429,4748],{"class":3849},[3832,9431,9432],{"class":3853},"api\n",[3801,9434,9435],{},[3770,9436,9437],{},"Що тут відбувається?",[3746,9439,9440,9446,9452,9461,9467,9473],{},[3749,9441,9442,9445],{},[3829,9443,9444],{},"createApi()"," — головна функція, яка створює весь API",[3749,9447,9448,9451],{},[3829,9449,9450],{},"reducerPath"," — ім'я, під яким дані зберігатимуться у Redux store",[3749,9453,9454,9456,9457,9460],{},[3829,9455,8840],{}," — інструмент для виконання HTTP-запитів (вбудований ",[3829,9458,9459],{},"fetch",")",[3749,9462,9463,9466],{},[3829,9464,9465],{},"endpoints"," — список усіх операцій з сервером",[3749,9468,9469,9472],{},[3829,9470,9471],{},"builder.query"," — описує операцію читання даних (GET)",[3749,9474,9475,9477],{},[3829,9476,9427],{}," — автоматично згенерований React-хук для використання у компонентах",[3809,9479,9481],{"id":9480},"крок-3-підключення-до-redux-store","Крок 3: Підключення до Redux Store",[3801,9483,9484],{},"Тепер потрібно інтегрувати наш API у Redux:",[3822,9486,9488],{"className":3824,"code":9487,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fstore\u002Findex.ts\nimport { configureStore } from '@reduxjs\u002Ftoolkit'\nimport { setupListeners } from '@reduxjs\u002Ftoolkit\u002Fquery'\nimport { api } from '@\u002Fservices\u002Fapi'\n\nexport const store = configureStore({\n    reducer: {\n        \u002F\u002F Додаємо автоматично згенерований редюсер\n        [api.reducerPath]: api.reducer,\n    },\n    middleware: (getDefaultMiddleware) =>\n        \u002F\u002F Додаємо middleware для керування кешем та підписками\n        getDefaultMiddleware().concat(api.middleware),\n})\n\n\u002F\u002F Увімкнути refetchOnFocus та refetchOnReconnect\nsetupListeners(store.dispatch)\n\nexport type RootState = ReturnType\u003Ctypeof store.getState>\nexport type AppDispatch = typeof store.dispatch\n",[3829,9489,9490,9495,9510,9526,9542,9546,9561,9568,9573,9587,9591,9608,9613,9635,9639,9643,9648,9663,9667,9696],{"__ignoreMap":3827},[3832,9491,9492],{"class":3834,"line":3835},[3832,9493,9494],{"class":3838},"\u002F\u002F src\u002Fstore\u002Findex.ts\n",[3832,9496,9497,9499,9501,9504,9506,9508],{"class":3834,"line":3842},[3832,9498,3846],{"class":3845},[3832,9500,3850],{"class":3849},[3832,9502,9503],{"class":3853},"configureStore",[3832,9505,3863],{"class":3849},[3832,9507,3866],{"class":3845},[3832,9509,3870],{"class":3869},[3832,9511,9512,9514,9516,9519,9521,9523],{"class":3834,"line":3873},[3832,9513,3846],{"class":3845},[3832,9515,3850],{"class":3849},[3832,9517,9518],{"class":3853},"setupListeners",[3832,9520,3863],{"class":3849},[3832,9522,3866],{"class":3845},[3832,9524,9525],{"class":3869}," '@reduxjs\u002Ftoolkit\u002Fquery'\n",[3832,9527,9528,9530,9532,9535,9537,9539],{"class":3834,"line":3880},[3832,9529,3846],{"class":3845},[3832,9531,3850],{"class":3849},[3832,9533,9534],{"class":3853},"api",[3832,9536,3863],{"class":3849},[3832,9538,3866],{"class":3845},[3832,9540,9541],{"class":3869}," '@\u002Fservices\u002Fapi'\n",[3832,9543,9544],{"class":3834,"line":3886},[3832,9545,3877],{"emptyLinePlaceholder":3876},[3832,9547,9548,9550,9552,9555,9557,9559],{"class":3834,"line":3900},[3832,9549,4105],{"class":3845},[3832,9551,4108],{"class":3889},[3832,9553,9554],{"class":4042}," store",[3832,9556,4114],{"class":3849},[3832,9558,9503],{"class":4117},[3832,9560,4267],{"class":3849},[3832,9562,9563,9566],{"class":3834,"line":3912},[3832,9564,9565],{"class":3853},"    reducer:",[3832,9567,3897],{"class":3849},[3832,9569,9570],{"class":3834,"line":3922},[3832,9571,9572],{"class":3838},"        \u002F\u002F Додаємо автоматично згенерований редюсер\n",[3832,9574,9575,9578,9580,9582,9585],{"class":3834,"line":3932},[3832,9576,9577],{"class":3853},"        [api.reducerPath]:",[3832,9579,9277],{"class":3853},[3832,9581,4183],{"class":3849},[3832,9583,9584],{"class":3853},"reducer",[3832,9586,4072],{"class":3849},[3832,9588,9589],{"class":3834,"line":3942},[3832,9590,4560],{"class":3849},[3832,9592,9593,9596,9598,9600,9603,9605],{"class":3834,"line":3948},[3832,9594,9595],{"class":4117},"    middleware",[3832,9597,4304],{"class":3853},[3832,9599,4307],{"class":3849},[3832,9601,9602],{"class":3853},"getDefaultMiddleware",[3832,9604,4313],{"class":3849},[3832,9606,9607],{"class":3889},"=>\n",[3832,9609,9610],{"class":3834,"line":3953},[3832,9611,9612],{"class":3838},"        \u002F\u002F Додаємо middleware для керування кешем та підписками\n",[3832,9614,9615,9618,9621,9624,9626,9628,9630,9633],{"class":3834,"line":3959},[3832,9616,9617],{"class":4117},"        getDefaultMiddleware",[3832,9619,9620],{"class":3849},"().",[3832,9622,9623],{"class":4117},"concat",[3832,9625,4162],{"class":3849},[3832,9627,9534],{"class":3853},[3832,9629,4183],{"class":3849},[3832,9631,9632],{"class":3853},"middleware",[3832,9634,5165],{"class":3849},[3832,9636,9637],{"class":3834,"line":3969},[3832,9638,4566],{"class":3849},[3832,9640,9641],{"class":3834,"line":3986},[3832,9642,3877],{"emptyLinePlaceholder":3876},[3832,9644,9645],{"class":3834,"line":4000},[3832,9646,9647],{"class":3838},"\u002F\u002F Увімкнути refetchOnFocus та refetchOnReconnect\n",[3832,9649,9650,9652,9654,9657,9659,9661],{"class":3834,"line":4020},[3832,9651,9518],{"class":4117},[3832,9653,4162],{"class":3849},[3832,9655,9656],{"class":3853},"store",[3832,9658,4183],{"class":3849},[3832,9660,4809],{"class":3853},[3832,9662,4168],{"class":3849},[3832,9664,9665],{"class":3834,"line":4025},[3832,9666,3877],{"emptyLinePlaceholder":3876},[3832,9668,9669,9671,9674,9677,9679,9682,9684,9687,9689,9691,9694],{"class":3834,"line":4030},[3832,9670,4105],{"class":3845},[3832,9672,9673],{"class":3889}," type",[3832,9675,9676],{"class":3893}," RootState",[3832,9678,4114],{"class":3849},[3832,9680,9681],{"class":3893},"ReturnType",[3832,9683,5084],{"class":3849},[3832,9685,9686],{"class":3889},"typeof",[3832,9688,9554],{"class":3853},[3832,9690,4183],{"class":3849},[3832,9692,9693],{"class":3853},"getState",[3832,9695,4898],{"class":3849},[3832,9697,9698,9700,9702,9705,9707,9709,9711,9713],{"class":3834,"line":4036},[3832,9699,4105],{"class":3845},[3832,9701,9673],{"class":3889},[3832,9703,9704],{"class":3893}," AppDispatch",[3832,9706,4114],{"class":3849},[3832,9708,9686],{"class":3889},[3832,9710,9554],{"class":3853},[3832,9712,4183],{"class":3849},[3832,9714,9715],{"class":3853},"dispatch\n",[3801,9717,9718],{},[3770,9719,9720],{},"Пояснення ключових моментів:",[8777,9722,9723,9758,9794],{},[8780,9724,9726,9732,9751],{"icon":8782,"label":9725},"🤔 Що таке api.reducer та навіщо він потрібен?",[3801,9727,9728,9731],{},[3829,9729,9730],{},"api.reducer"," — це автоматично згенерований Redux редюсер, який зберігає:",[3746,9733,9734,9737,9745,9748],{},[3749,9735,9736],{},"Завантажені дані з сервера (кеш)",[3749,9738,9739,9740,3857,9742,9460],{},"Стан завантаження для кожного запиту (",[3829,9741,4371],{},[3829,9743,9744],{},"isFetching",[3749,9746,9747],{},"Помилки, якщо запити провалились",[3749,9749,9750],{},"Метадані про підписки (які компоненти зараз використовують які дані)",[3801,9752,9753,9754,9757],{},"Ви ",[3770,9755,9756],{},"ніколи не пишете цей редюсер вручну"," — RTK Query генерує його автоматично на основі вашого опису ендпоінтів.",[8780,9759,9761,9768],{"icon":8782,"label":9760},"🤔 Навіщо потрібен api.middleware?",[3801,9762,9763,9764,9767],{},"Middleware (",[3817,9765,9766],{},"проміжний обробник",") виконує важливі фонові завдання:",[3746,9769,9770,9776,9782,9788],{},[3749,9771,9772,9775],{},[3770,9773,9774],{},"Керування підписками:"," відслідковує, які компоненти використовують які дані",[3749,9777,9778,9781],{},[3770,9779,9780],{},"Автоматичне очищення:"," видаляє застарілі дані з пам'яті через певний час",[3749,9783,9784,9787],{},[3770,9785,9786],{},"Дедуплікація запитів:"," якщо 5 компонентів запитують одні дані одночасно — виконує лише 1 реальний HTTP-запит",[3749,9789,9790,9793],{},[3770,9791,9792],{},"Refetch логіка:"," автоматично оновлює дані при поверненні з фону або відновленні інтернету",[8780,9795,9797,9800,9814],{"icon":8782,"label":9796},"🤔 Що робить setupListeners?",[3801,9798,9799],{},"Ця функція підключає слухачів подій для:",[3746,9801,9802,9808],{},[3749,9803,9804,9807],{},[3770,9805,9806],{},"Focus detection:"," коли користувач повертається в застосунок з фону",[3749,9809,9810,9813],{},[3770,9811,9812],{},"Network detection:"," коли інтернет з'єднання відновлюється після розриву",[3801,9815,9816],{},"Завдяки цьому RTK Query може автоматично оновлювати дані у потрібний момент без вашого коду!",[3809,9818,9820],{"id":9819},"крок-4-використання-у-компоненті","Крок 4: Використання у компоненті",[3801,9822,9823],{},"Тепер можемо використати наш API у React Native компоненті:",[3822,9825,9827],{"className":4592,"code":9826,"language":4594,"meta":3827,"style":3827},"\u002F\u002F app\u002Fscreens\u002FPostsScreen.tsx\nimport React from 'react'\nimport { View, Text, FlatList, ActivityIndicator, StyleSheet } from 'react-native'\nimport { useGetPostsQuery } from '@\u002Fservices\u002Fapi'\n\nexport function PostsScreen() {\n    \u002F\u002F Викликаємо хук — запит виконається автоматично!\n    const { data, isLoading, error } = useGetPostsQuery()\n\n    \u002F\u002F Показуємо індикатор завантаження\n    if (isLoading) {\n        return (\n            \u003CView style={styles.center}>\n                \u003CActivityIndicator size=\"large\" color=\"#3b82f6\" \u002F>\n                \u003CText style={styles.loadingText}>Завантаження постів...\u003C\u002FText>\n            \u003C\u002FView>\n        )\n    }\n\n    \u002F\u002F Обробка помилки\n    if (error) {\n        return (\n            \u003CView style={styles.center}>\n                \u003CText style={styles.errorText}>\n                    Помилка: {error.toString()}\n                \u003C\u002FText>\n            \u003C\u002FView>\n        )\n    }\n\n    \u002F\u002F Відображаємо дані\n    return (\n        \u003CFlatList\n            data={data}\n            keyExtractor={(item) => item.id.toString()}\n            renderItem={({ item }) => (\n                \u003CView style={styles.card}>\n                    \u003CText style={styles.title}>{item.title}\u003C\u002FText>\n                    \u003CText style={styles.body}>{item.body}\u003C\u002FText>\n                \u003C\u002FView>\n            )}\n        \u002F>\n    )\n}\n\nconst styles = StyleSheet.create({\n    center: {\n        flex: 1,\n        justifyContent: 'center',\n        alignItems: 'center',\n        padding: 20,\n    },\n    loadingText: {\n        marginTop: 12,\n        fontSize: 14,\n        color: '#64748b',\n    },\n    errorText: {\n        fontSize: 16,\n        color: '#dc2626',\n        textAlign: 'center',\n    },\n    card: {\n        backgroundColor: '#ffffff',\n        padding: 16,\n        marginHorizontal: 16,\n        marginTop: 12,\n        borderRadius: 12,\n        shadowColor: '#000',\n        shadowOffset: { width: 0, height: 2 },\n        shadowOpacity: 0.1,\n        shadowRadius: 4,\n        elevation: 3,\n    },\n    title: {\n        fontSize: 16,\n        fontWeight: '700',\n        color: '#0f172a',\n        marginBottom: 8,\n    },\n    body: {\n        fontSize: 14,\n        color: '#64748b',\n        lineHeight: 20,\n    },\n})\n",[3829,9828,9829,9834,9844,9875,9889,9893,9904,9909,9931,9935,9940,9950,9956,9980,10003,10035,10044,10049,10053,10057,10062,10072,10078,10100,10123,10142,10151,10159,10163,10167,10171,10176,10182,10188,10200,10230,10248,10270,10309,10348,10356,10363,10367,10371,10375,10379,10397,10404,10414,10424,10433,10443,10447,10454,10464,10473,10483,10487,10494,10503,10512,10521,10525,10532,10543,10552,10562,10571,10581,10591,10615,10626,10637,10648,10653,10661,10670,10681,10691,10702,10707,10715,10724,10733,10743,10748],{"__ignoreMap":3827},[3832,9830,9831],{"class":3834,"line":3835},[3832,9832,9833],{"class":3838},"\u002F\u002F app\u002Fscreens\u002FPostsScreen.tsx\n",[3832,9835,9836,9838,9840,9842],{"class":3834,"line":3842},[3832,9837,3846],{"class":3845},[3832,9839,4608],{"class":3853},[3832,9841,5856],{"class":3845},[3832,9843,4621],{"class":3869},[3832,9845,9846,9848,9850,9852,9854,9856,9858,9860,9862,9864,9866,9869,9871,9873],{"class":3834,"line":3873},[3832,9847,3846],{"class":3845},[3832,9849,3850],{"class":3849},[3832,9851,4630],{"class":3853},[3832,9853,3857],{"class":3849},[3832,9855,4635],{"class":3853},[3832,9857,3857],{"class":3849},[3832,9859,4640],{"class":3853},[3832,9861,3857],{"class":3849},[3832,9863,4645],{"class":3853},[3832,9865,3857],{"class":3849},[3832,9867,9868],{"class":3853},"StyleSheet",[3832,9870,3863],{"class":3849},[3832,9872,3866],{"class":3845},[3832,9874,4652],{"class":3869},[3832,9876,9877,9879,9881,9883,9885,9887],{"class":3834,"line":3880},[3832,9878,3846],{"class":3845},[3832,9880,3850],{"class":3849},[3832,9882,9427],{"class":3853},[3832,9884,3863],{"class":3849},[3832,9886,3866],{"class":3845},[3832,9888,9541],{"class":3869},[3832,9890,9891],{"class":3834,"line":3886},[3832,9892,3877],{"emptyLinePlaceholder":3876},[3832,9894,9895,9897,9899,9902],{"class":3834,"line":3900},[3832,9896,4105],{"class":3845},[3832,9898,4699],{"class":3889},[3832,9900,9901],{"class":4117}," PostsScreen",[3832,9903,4705],{"class":3849},[3832,9905,9906],{"class":3834,"line":3912},[3832,9907,9908],{"class":3838},"    \u002F\u002F Викликаємо хук — запит виконається автоматично!\n",[3832,9910,9911,9913,9915,9917,9919,9921,9923,9925,9927,9929],{"class":3834,"line":3922},[3832,9912,4710],{"class":3889},[3832,9914,3850],{"class":3849},[3832,9916,6565],{"class":4042},[3832,9918,3857],{"class":3849},[3832,9920,4371],{"class":4042},[3832,9922,3857],{"class":3849},[3832,9924,4386],{"class":4042},[3832,9926,4748],{"class":3849},[3832,9928,9427],{"class":4117},[3832,9930,4230],{"class":3849},[3832,9932,9933],{"class":3834,"line":3932},[3832,9934,3877],{"emptyLinePlaceholder":3876},[3832,9936,9937],{"class":3834,"line":3942},[3832,9938,9939],{"class":3838},"    \u002F\u002F Показуємо індикатор завантаження\n",[3832,9941,9942,9944,9946,9948],{"class":3834,"line":3948},[3832,9943,4821],{"class":3845},[3832,9945,4307],{"class":3849},[3832,9947,4371],{"class":3853},[3832,9949,4189],{"class":3849},[3832,9951,9952,9954],{"class":3834,"line":3953},[3832,9953,4220],{"class":3845},[3832,9955,4914],{"class":3849},[3832,9957,9958,9960,9962,9964,9966,9968,9971,9973,9976,9978],{"class":3834,"line":3959},[3832,9959,7532],{"class":4834},[3832,9961,4630],{"class":3893},[3832,9963,8467],{"class":4840},[3832,9965,4844],{"class":3849},[3832,9967,4885],{"class":3889},[3832,9969,9970],{"class":3853},"styles",[3832,9972,4183],{"class":4947},[3832,9974,9975],{"class":3853},"center",[3832,9977,4890],{"class":3889},[3832,9979,4898],{"class":4834},[3832,9981,9982,9985,9987,9989,9991,9993,9996,9998,10001],{"class":3834,"line":3969},[3832,9983,9984],{"class":4834},"                \u003C",[3832,9986,4645],{"class":3893},[3832,9988,4841],{"class":4840},[3832,9990,4844],{"class":3849},[3832,9992,4847],{"class":3869},[3832,9994,9995],{"class":4840}," color",[3832,9997,4844],{"class":3849},[3832,9999,10000],{"class":3869},"\"#3b82f6\"",[3832,10002,4850],{"class":4834},[3832,10004,10005,10007,10009,10011,10013,10015,10017,10019,10022,10024,10026,10029,10031,10033],{"class":3834,"line":3986},[3832,10006,9984],{"class":4834},[3832,10008,4635],{"class":3893},[3832,10010,8467],{"class":4840},[3832,10012,4844],{"class":3849},[3832,10014,4885],{"class":3889},[3832,10016,9970],{"class":3853},[3832,10018,4183],{"class":4947},[3832,10020,10021],{"class":3853},"loadingText",[3832,10023,4890],{"class":3889},[3832,10025,4879],{"class":4834},[3832,10027,10028],{"class":3849},"Завантаження постів...",[3832,10030,4893],{"class":4834},[3832,10032,4635],{"class":3893},[3832,10034,4898],{"class":4834},[3832,10036,10037,10040,10042],{"class":3834,"line":4000},[3832,10038,10039],{"class":4834},"            \u003C\u002F",[3832,10041,4630],{"class":3893},[3832,10043,4898],{"class":4834},[3832,10045,10046],{"class":3834,"line":4020},[3832,10047,10048],{"class":3849},"        )\n",[3832,10050,10051],{"class":3834,"line":4025},[3832,10052,4236],{"class":3849},[3832,10054,10055],{"class":3834,"line":4030},[3832,10056,3877],{"emptyLinePlaceholder":3876},[3832,10058,10059],{"class":3834,"line":4036},[3832,10060,10061],{"class":3838},"    \u002F\u002F Обробка помилки\n",[3832,10063,10064,10066,10068,10070],{"class":3834,"line":4054},[3832,10065,4821],{"class":3845},[3832,10067,4307],{"class":3849},[3832,10069,4386],{"class":3853},[3832,10071,4189],{"class":3849},[3832,10073,10074,10076],{"class":3834,"line":4063},[3832,10075,4220],{"class":3845},[3832,10077,4914],{"class":3849},[3832,10079,10080,10082,10084,10086,10088,10090,10092,10094,10096,10098],{"class":3834,"line":4075},[3832,10081,7532],{"class":4834},[3832,10083,4630],{"class":3893},[3832,10085,8467],{"class":4840},[3832,10087,4844],{"class":3849},[3832,10089,4885],{"class":3889},[3832,10091,9970],{"class":3853},[3832,10093,4183],{"class":4947},[3832,10095,9975],{"class":3853},[3832,10097,4890],{"class":3889},[3832,10099,4898],{"class":4834},[3832,10101,10102,10104,10106,10108,10110,10112,10114,10116,10119,10121],{"class":3834,"line":4086},[3832,10103,9984],{"class":4834},[3832,10105,4635],{"class":3893},[3832,10107,8467],{"class":4840},[3832,10109,4844],{"class":3849},[3832,10111,4885],{"class":3889},[3832,10113,9970],{"class":3853},[3832,10115,4183],{"class":4947},[3832,10117,10118],{"class":3853},"errorText",[3832,10120,4890],{"class":3889},[3832,10122,4898],{"class":4834},[3832,10124,10125,10128,10130,10132,10134,10137,10140],{"class":3834,"line":4091},[3832,10126,10127],{"class":3849},"                    Помилка: ",[3832,10129,4885],{"class":3889},[3832,10131,4386],{"class":3853},[3832,10133,4183],{"class":4947},[3832,10135,10136],{"class":4117},"toString",[3832,10138,10139],{"class":4947},"()",[3832,10141,3945],{"class":3889},[3832,10143,10144,10147,10149],{"class":3834,"line":4096},[3832,10145,10146],{"class":4834},"                \u003C\u002F",[3832,10148,4635],{"class":3893},[3832,10150,4898],{"class":4834},[3832,10152,10153,10155,10157],{"class":3834,"line":4102},[3832,10154,10039],{"class":4834},[3832,10156,4630],{"class":3893},[3832,10158,4898],{"class":4834},[3832,10160,10161],{"class":3834,"line":4123},[3832,10162,10048],{"class":3849},[3832,10164,10165],{"class":3834,"line":4131},[3832,10166,4236],{"class":3849},[3832,10168,10169],{"class":3834,"line":4145},[3832,10170,3877],{"emptyLinePlaceholder":3876},[3832,10172,10173],{"class":3834,"line":4171},[3832,10174,10175],{"class":3838},"    \u002F\u002F Відображаємо дані\n",[3832,10177,10178,10180],{"class":3834,"line":4192},[3832,10179,4911],{"class":3845},[3832,10181,4914],{"class":3849},[3832,10183,10184,10186],{"class":3834,"line":4211},[3832,10185,4919],{"class":4834},[3832,10187,4922],{"class":3893},[3832,10189,10190,10192,10194,10196,10198],{"class":3834,"line":4217},[3832,10191,4927],{"class":4840},[3832,10193,4844],{"class":3849},[3832,10195,4885],{"class":3889},[3832,10197,6565],{"class":3853},[3832,10199,3945],{"class":3889},[3832,10201,10202,10204,10206,10208,10210,10212,10214,10216,10218,10220,10222,10224,10226,10228],{"class":3834,"line":4233},[3832,10203,4940],{"class":4840},[3832,10205,4844],{"class":3849},[3832,10207,4885],{"class":3889},[3832,10209,4162],{"class":4947},[3832,10211,4950],{"class":3853},[3832,10213,4313],{"class":4947},[3832,10215,4140],{"class":3889},[3832,10217,4957],{"class":3853},[3832,10219,4183],{"class":4947},[3832,10221,4962],{"class":3853},[3832,10223,4183],{"class":4947},[3832,10225,10136],{"class":4117},[3832,10227,10139],{"class":4947},[3832,10229,3945],{"class":3889},[3832,10231,10232,10234,10236,10238,10240,10242,10244,10246],{"class":3834,"line":4239},[3832,10233,4969],{"class":4840},[3832,10235,4844],{"class":3849},[3832,10237,4885],{"class":3889},[3832,10239,4976],{"class":4947},[3832,10241,4950],{"class":3853},[3832,10243,4981],{"class":4947},[3832,10245,4140],{"class":3889},[3832,10247,4914],{"class":4947},[3832,10249,10250,10252,10254,10256,10258,10260,10262,10264,10266,10268],{"class":3834,"line":4244},[3832,10251,9984],{"class":4834},[3832,10253,4630],{"class":3893},[3832,10255,8467],{"class":4840},[3832,10257,4844],{"class":3849},[3832,10259,4885],{"class":3889},[3832,10261,9970],{"class":3853},[3832,10263,4183],{"class":4947},[3832,10265,3741],{"class":3853},[3832,10267,4890],{"class":3889},[3832,10269,4898],{"class":4834},[3832,10271,10272,10275,10277,10279,10281,10283,10285,10287,10289,10291,10293,10295,10297,10299,10301,10303,10305,10307],{"class":3834,"line":4249},[3832,10273,10274],{"class":4834},"                    \u003C",[3832,10276,4635],{"class":3893},[3832,10278,8467],{"class":4840},[3832,10280,4844],{"class":3849},[3832,10282,4885],{"class":3889},[3832,10284,9970],{"class":3853},[3832,10286,4183],{"class":4947},[3832,10288,4998],{"class":3853},[3832,10290,4890],{"class":3889},[3832,10292,4879],{"class":4834},[3832,10294,4885],{"class":3889},[3832,10296,4950],{"class":3853},[3832,10298,4183],{"class":4947},[3832,10300,4998],{"class":3853},[3832,10302,4890],{"class":3889},[3832,10304,4893],{"class":4834},[3832,10306,4635],{"class":3893},[3832,10308,4898],{"class":4834},[3832,10310,10311,10313,10315,10317,10319,10321,10323,10325,10328,10330,10332,10334,10336,10338,10340,10342,10344,10346],{"class":3834,"line":4255},[3832,10312,10274],{"class":4834},[3832,10314,4635],{"class":3893},[3832,10316,8467],{"class":4840},[3832,10318,4844],{"class":3849},[3832,10320,4885],{"class":3889},[3832,10322,9970],{"class":3853},[3832,10324,4183],{"class":4947},[3832,10326,10327],{"class":3853},"body",[3832,10329,4890],{"class":3889},[3832,10331,4879],{"class":4834},[3832,10333,4885],{"class":3889},[3832,10335,4950],{"class":3853},[3832,10337,4183],{"class":4947},[3832,10339,10327],{"class":3853},[3832,10341,4890],{"class":3889},[3832,10343,4893],{"class":4834},[3832,10345,4635],{"class":3893},[3832,10347,4898],{"class":4834},[3832,10349,10350,10352,10354],{"class":3834,"line":4270},[3832,10351,10146],{"class":4834},[3832,10353,4630],{"class":3893},[3832,10355,4898],{"class":4834},[3832,10357,10358,10361],{"class":3834,"line":4281},[3832,10359,10360],{"class":4947},"            )",[3832,10362,3945],{"class":3889},[3832,10364,10365],{"class":3834,"line":4289},[3832,10366,5013],{"class":4834},[3832,10368,10369],{"class":3834,"line":4298},[3832,10370,5018],{"class":3849},[3832,10372,10373],{"class":3834,"line":4320},[3832,10374,3945],{"class":3849},[3832,10376,10377],{"class":3834,"line":4326},[3832,10378,3877],{"emptyLinePlaceholder":3876},[3832,10380,10381,10383,10386,10388,10390,10392,10395],{"class":3834,"line":4332},[3832,10382,4039],{"class":3889},[3832,10384,10385],{"class":4042}," styles",[3832,10387,4114],{"class":3849},[3832,10389,9868],{"class":3853},[3832,10391,4183],{"class":3849},[3832,10393,10394],{"class":4117},"create",[3832,10396,4267],{"class":3849},[3832,10398,10399,10402],{"class":3834,"line":4363},[3832,10400,10401],{"class":3853},"    center:",[3832,10403,3897],{"class":3849},[3832,10405,10406,10409,10412],{"class":3834,"line":4379},[3832,10407,10408],{"class":3853},"        flex:",[3832,10410,10411],{"class":5726}," 1",[3832,10413,4072],{"class":3849},[3832,10415,10416,10419,10422],{"class":3834,"line":4394},[3832,10417,10418],{"class":3853},"        justifyContent:",[3832,10420,10421],{"class":3869}," 'center'",[3832,10423,4072],{"class":3849},[3832,10425,10426,10429,10431],{"class":3834,"line":4400},[3832,10427,10428],{"class":3853},"        alignItems:",[3832,10430,10421],{"class":3869},[3832,10432,4072],{"class":3849},[3832,10434,10435,10438,10441],{"class":3834,"line":4406},[3832,10436,10437],{"class":3853},"        padding:",[3832,10439,10440],{"class":5726}," 20",[3832,10442,4072],{"class":3849},[3832,10444,10445],{"class":3834,"line":4437},[3832,10446,4560],{"class":3849},[3832,10448,10449,10452],{"class":3834,"line":4451},[3832,10450,10451],{"class":3853},"    loadingText:",[3832,10453,3897],{"class":3849},[3832,10455,10456,10459,10462],{"class":3834,"line":4470},[3832,10457,10458],{"class":3853},"        marginTop:",[3832,10460,10461],{"class":5726}," 12",[3832,10463,4072],{"class":3849},[3832,10465,10466,10468,10471],{"class":3834,"line":4475},[3832,10467,6986],{"class":3853},[3832,10469,10470],{"class":5726}," 14",[3832,10472,4072],{"class":3849},[3832,10474,10475,10478,10481],{"class":3834,"line":4481},[3832,10476,10477],{"class":3853},"        color:",[3832,10479,10480],{"class":3869}," '#64748b'",[3832,10482,4072],{"class":3849},[3832,10484,10485],{"class":3834,"line":4511},[3832,10486,4560],{"class":3849},[3832,10488,10489,10492],{"class":3834,"line":4524},[3832,10490,10491],{"class":3853},"    errorText:",[3832,10493,3897],{"class":3849},[3832,10495,10496,10498,10501],{"class":3834,"line":4552},[3832,10497,6986],{"class":3853},[3832,10499,10500],{"class":5726}," 16",[3832,10502,4072],{"class":3849},[3832,10504,10505,10507,10510],{"class":3834,"line":4557},[3832,10506,10477],{"class":3853},[3832,10508,10509],{"class":3869}," '#dc2626'",[3832,10511,4072],{"class":3849},[3832,10513,10514,10517,10519],{"class":3834,"line":4563},[3832,10515,10516],{"class":3853},"        textAlign:",[3832,10518,10421],{"class":3869},[3832,10520,4072],{"class":3849},[3832,10522,10523],{"class":3834,"line":4569},[3832,10524,4560],{"class":3849},[3832,10526,10527,10530],{"class":3834,"line":4574},[3832,10528,10529],{"class":3853},"    card:",[3832,10531,3897],{"class":3849},[3832,10533,10535,10538,10541],{"class":3834,"line":10534},64,[3832,10536,10537],{"class":3853},"        backgroundColor:",[3832,10539,10540],{"class":3869}," '#ffffff'",[3832,10542,4072],{"class":3849},[3832,10544,10546,10548,10550],{"class":3834,"line":10545},65,[3832,10547,10437],{"class":3853},[3832,10549,10500],{"class":5726},[3832,10551,4072],{"class":3849},[3832,10553,10555,10558,10560],{"class":3834,"line":10554},66,[3832,10556,10557],{"class":3853},"        marginHorizontal:",[3832,10559,10500],{"class":5726},[3832,10561,4072],{"class":3849},[3832,10563,10565,10567,10569],{"class":3834,"line":10564},67,[3832,10566,10458],{"class":3853},[3832,10568,10461],{"class":5726},[3832,10570,4072],{"class":3849},[3832,10572,10574,10577,10579],{"class":3834,"line":10573},68,[3832,10575,10576],{"class":3853},"        borderRadius:",[3832,10578,10461],{"class":5726},[3832,10580,4072],{"class":3849},[3832,10582,10584,10587,10589],{"class":3834,"line":10583},69,[3832,10585,10586],{"class":3853},"        shadowColor:",[3832,10588,8491],{"class":3869},[3832,10590,4072],{"class":3849},[3832,10592,10594,10597,10599,10602,10605,10607,10610,10613],{"class":3834,"line":10593},70,[3832,10595,10596],{"class":3853},"        shadowOffset:",[3832,10598,3850],{"class":3849},[3832,10600,10601],{"class":3853},"width:",[3832,10603,10604],{"class":5726}," 0",[3832,10606,3857],{"class":3849},[3832,10608,10609],{"class":3853},"height:",[3832,10611,10612],{"class":5726}," 2",[3832,10614,5145],{"class":3849},[3832,10616,10618,10621,10624],{"class":3834,"line":10617},71,[3832,10619,10620],{"class":3853},"        shadowOpacity:",[3832,10622,10623],{"class":5726}," 0.1",[3832,10625,4072],{"class":3849},[3832,10627,10629,10632,10635],{"class":3834,"line":10628},72,[3832,10630,10631],{"class":3853},"        shadowRadius:",[3832,10633,10634],{"class":5726}," 4",[3832,10636,4072],{"class":3849},[3832,10638,10640,10643,10646],{"class":3834,"line":10639},73,[3832,10641,10642],{"class":3853},"        elevation:",[3832,10644,10645],{"class":5726}," 3",[3832,10647,4072],{"class":3849},[3832,10649,10651],{"class":3834,"line":10650},74,[3832,10652,4560],{"class":3849},[3832,10654,10656,10659],{"class":3834,"line":10655},75,[3832,10657,10658],{"class":3853},"    title:",[3832,10660,3897],{"class":3849},[3832,10662,10664,10666,10668],{"class":3834,"line":10663},76,[3832,10665,6986],{"class":3853},[3832,10667,10500],{"class":5726},[3832,10669,4072],{"class":3849},[3832,10671,10673,10676,10679],{"class":3834,"line":10672},77,[3832,10674,10675],{"class":3853},"        fontWeight:",[3832,10677,10678],{"class":3869}," '700'",[3832,10680,4072],{"class":3849},[3832,10682,10684,10686,10689],{"class":3834,"line":10683},78,[3832,10685,10477],{"class":3853},[3832,10687,10688],{"class":3869}," '#0f172a'",[3832,10690,4072],{"class":3849},[3832,10692,10694,10697,10700],{"class":3834,"line":10693},79,[3832,10695,10696],{"class":3853},"        marginBottom:",[3832,10698,10699],{"class":5726}," 8",[3832,10701,4072],{"class":3849},[3832,10703,10705],{"class":3834,"line":10704},80,[3832,10706,4560],{"class":3849},[3832,10708,10710,10713],{"class":3834,"line":10709},81,[3832,10711,10712],{"class":3853},"    body:",[3832,10714,3897],{"class":3849},[3832,10716,10718,10720,10722],{"class":3834,"line":10717},82,[3832,10719,6986],{"class":3853},[3832,10721,10470],{"class":5726},[3832,10723,4072],{"class":3849},[3832,10725,10727,10729,10731],{"class":3834,"line":10726},83,[3832,10728,10477],{"class":3853},[3832,10730,10480],{"class":3869},[3832,10732,4072],{"class":3849},[3832,10734,10736,10739,10741],{"class":3834,"line":10735},84,[3832,10737,10738],{"class":3853},"        lineHeight:",[3832,10740,10440],{"class":5726},[3832,10742,4072],{"class":3849},[3832,10744,10746],{"class":3834,"line":10745},85,[3832,10747,4560],{"class":3849},[3832,10749,10751],{"class":3834,"line":10750},86,[3832,10752,4566],{"class":3849},[3801,10754,10755],{},[3770,10756,10757],{},"Магія RTK Query в дії:",[5430,10759,10760,10764,10771,10775,10778,10782,10791,10795,10805,10808],{},[3809,10761,10763],{"id":10762},"компонент-монтується","Компонент монтується",[3801,10765,10766,10767,10770],{},"React викликає ",[3829,10768,10769],{},"useGetPostsQuery()"," при рендері компонента",[3809,10772,10774],{"id":10773},"автоматичний-запит","Автоматичний запит",[3801,10776,10777],{},"RTK Query перевіряє: є дані у кеші? Якщо немає — відправляє HTTP GET запит",[3809,10779,10781],{"id":10780},"оновлення-стану","Оновлення стану",[3801,10783,10784,10785,3857,10788],{},"Поки запит виконується: ",[3829,10786,10787],{},"isLoading = true",[3829,10789,10790],{},"data = undefined",[3809,10792,10794],{"id":10793},"отримання-результату","Отримання результату",[3801,10796,10797,10798,3857,10801,10804],{},"Коли сервер відповідає: ",[3829,10799,10800],{},"isLoading = false",[3829,10802,10803],{},"data = [...]"," — компонент ререндериться",[3809,10806,942],{"id":10807},"кешування",[3801,10809,10810,10811,10813],{},"Дані зберігаються у Redux store. Наступний виклик ",[3829,10812,10769],{}," поверне їх миттєво!",[3809,10815,10817,10818],{"id":10816},"розуміння-архітектури-що-генерує-createapi","Розуміння архітектури: що генерує ",[3829,10819,6153],{},[3801,10821,10822],{},"Давайте візуалізуємо, що відбувається під капотом:",[8090,10824,10826],{"alt":10825},"Архітектура RTK Query",[3822,10827,10829],{"className":8095,"code":10828,"language":8097,"meta":3827,"style":3827},"@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\nskinparam defaultFontName \"Helvetica\"\n\npackage \"Ваш код (пишете ви)\" {\n    [createApi(\\{...\\})] as CreateApi #DBEAFE\n}\n\npackage \"Автоматично генерується RTK Query\" {\n    [api.reducer] as Reducer #DCFCE7\n    [api.middleware] as Middleware #FEF3C7\n    [useGetPostsQuery()] as Hook #FED7AA\n    [endpoints.getPosts] as Endpoint #E0E7FF\n}\n\npackage \"Redux Store (керує станом)\" {\n    [State Tree] as State #F3F4F6\n}\n\npackage \"React Components (UI)\" {\n    [PostsScreen] as Component #FECACA\n}\n\nCreateApi --> Reducer : генерує\nCreateApi --> Middleware : генерує\nCreateApi --> Hook : генерує\nCreateApi --> Endpoint : генерує\n\nReducer --> State : зберігає кеш\nMiddleware --> State : керує підписками\n\nComponent --> Hook : викликає\nHook --> Endpoint : запускає запит\nEndpoint --> Middleware : обробляє життєвий цикл\nMiddleware --> Reducer : оновлює дані\n\n@enduml\n",[3829,10830,10831,10835,10839,10843,10847,10851,10856,10861,10865,10869,10874,10879,10884,10889,10894,10898,10902,10907,10912,10916,10920,10925,10930,10934,10938,10943,10948,10953,10958,10962,10967,10972,10976,10981,10986,10991,10996,11000],{"__ignoreMap":3827},[3832,10832,10833],{"class":3834,"line":3835},[3832,10834,8104],{},[3832,10836,10837],{"class":3834,"line":3842},[3832,10838,8109],{},[3832,10840,10841],{"class":3834,"line":3873},[3832,10842,8114],{},[3832,10844,10845],{"class":3834,"line":3880},[3832,10846,8119],{},[3832,10848,10849],{"class":3834,"line":3886},[3832,10850,3877],{"emptyLinePlaceholder":3876},[3832,10852,10853],{"class":3834,"line":3900},[3832,10854,10855],{},"package \"Ваш код (пишете ви)\" {\n",[3832,10857,10858],{"class":3834,"line":3912},[3832,10859,10860],{},"    [createApi(\\{...\\})] as CreateApi #DBEAFE\n",[3832,10862,10863],{"class":3834,"line":3922},[3832,10864,3945],{},[3832,10866,10867],{"class":3834,"line":3932},[3832,10868,3877],{"emptyLinePlaceholder":3876},[3832,10870,10871],{"class":3834,"line":3942},[3832,10872,10873],{},"package \"Автоматично генерується RTK Query\" {\n",[3832,10875,10876],{"class":3834,"line":3948},[3832,10877,10878],{},"    [api.reducer] as Reducer #DCFCE7\n",[3832,10880,10881],{"class":3834,"line":3953},[3832,10882,10883],{},"    [api.middleware] as Middleware #FEF3C7\n",[3832,10885,10886],{"class":3834,"line":3959},[3832,10887,10888],{},"    [useGetPostsQuery()] as Hook #FED7AA\n",[3832,10890,10891],{"class":3834,"line":3969},[3832,10892,10893],{},"    [endpoints.getPosts] as Endpoint #E0E7FF\n",[3832,10895,10896],{"class":3834,"line":3986},[3832,10897,3945],{},[3832,10899,10900],{"class":3834,"line":4000},[3832,10901,3877],{"emptyLinePlaceholder":3876},[3832,10903,10904],{"class":3834,"line":4020},[3832,10905,10906],{},"package \"Redux Store (керує станом)\" {\n",[3832,10908,10909],{"class":3834,"line":4025},[3832,10910,10911],{},"    [State Tree] as State #F3F4F6\n",[3832,10913,10914],{"class":3834,"line":4030},[3832,10915,3945],{},[3832,10917,10918],{"class":3834,"line":4036},[3832,10919,3877],{"emptyLinePlaceholder":3876},[3832,10921,10922],{"class":3834,"line":4054},[3832,10923,10924],{},"package \"React Components (UI)\" {\n",[3832,10926,10927],{"class":3834,"line":4063},[3832,10928,10929],{},"    [PostsScreen] as Component #FECACA\n",[3832,10931,10932],{"class":3834,"line":4075},[3832,10933,3945],{},[3832,10935,10936],{"class":3834,"line":4086},[3832,10937,3877],{"emptyLinePlaceholder":3876},[3832,10939,10940],{"class":3834,"line":4091},[3832,10941,10942],{},"CreateApi --> Reducer : генерує\n",[3832,10944,10945],{"class":3834,"line":4096},[3832,10946,10947],{},"CreateApi --> Middleware : генерує\n",[3832,10949,10950],{"class":3834,"line":4102},[3832,10951,10952],{},"CreateApi --> Hook : генерує\n",[3832,10954,10955],{"class":3834,"line":4123},[3832,10956,10957],{},"CreateApi --> Endpoint : генерує\n",[3832,10959,10960],{"class":3834,"line":4131},[3832,10961,3877],{"emptyLinePlaceholder":3876},[3832,10963,10964],{"class":3834,"line":4145},[3832,10965,10966],{},"Reducer --> State : зберігає кеш\n",[3832,10968,10969],{"class":3834,"line":4171},[3832,10970,10971],{},"Middleware --> State : керує підписками\n",[3832,10973,10974],{"class":3834,"line":4192},[3832,10975,3877],{"emptyLinePlaceholder":3876},[3832,10977,10978],{"class":3834,"line":4211},[3832,10979,10980],{},"Component --> Hook : викликає\n",[3832,10982,10983],{"class":3834,"line":4217},[3832,10984,10985],{},"Hook --> Endpoint : запускає запит\n",[3832,10987,10988],{"class":3834,"line":4233},[3832,10989,10990],{},"Endpoint --> Middleware : обробляє життєвий цикл\n",[3832,10992,10993],{"class":3834,"line":4239},[3832,10994,10995],{},"Middleware --> Reducer : оновлює дані\n",[3832,10997,10998],{"class":3834,"line":4244},[3832,10999,3877],{"emptyLinePlaceholder":3876},[3832,11001,11002],{"class":3834,"line":4249},[3832,11003,8288],{},[3809,11005,11007,11008],{"id":11006},"поглиблене-налаштування-параметри-createapi","Поглиблене налаштування: Параметри ",[3829,11009,6153],{},[3801,11011,11012],{},"Тепер розглянемо всі важливі параметри конфігурації детальніше:",[3822,11014,11016],{"className":3824,"code":11015,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fservices\u002FtripsApi.ts\nimport { createApi, fetchBaseQuery } from '@reduxjs\u002Ftoolkit\u002Fquery\u002Freact'\nimport { Platform } from 'react-native'\nimport Constants from 'expo-constants'\n\n\u002F**\n * Функція для визначення правильної URL адреси в залежності від середовища.\n * Це критично для React Native, бо localhost працює по-різному:\n * - iOS Simulator: localhost = комп'ютер розробника\n * - Android Emulator: localhost = сам емулятор (потрібно 10.0.2.2)\n * - Реальний пристрій: потрібна IP-адреса комп'ютера в локальній мережі\n *\u002F\nconst getBaseUrl = (): string => {\n    \u002F\u002F Для Android емулятора використовуємо спеціальну адресу\n    if (Platform.OS === 'android') {\n        return 'http:\u002F\u002F10.0.2.2:3000'\n    }\n    \n    \u002F\u002F Для реальних пристроїв отримуємо IP з Expo\n    const hostUri = Constants.expoConfig?.hostUri\n    if (hostUri) {\n        const ip = hostUri.split(':').shift()\n        if (ip) return `http:\u002F\u002F${ip}:3000`\n    }\n    \n    \u002F\u002F Fallback для iOS Simulator\n    return 'http:\u002F\u002Flocalhost:3000'\n}\n\ninterface Trip {\n    id: string\n    title: string\n    region: string\n    startDate: string\n}\n\nexport const tripsApi = createApi({\n    \u002F\u002F 1️⃣ REDUCER PATH: Унікальне ім'я для Redux store\n    reducerPath: 'tripsApi',\n    \n    \u002F\u002F 2️⃣ BASE QUERY: Налаштування HTTP-клієнта\n    baseQuery: fetchBaseQuery({\n        baseUrl: getBaseUrl(),\n        \n        \u002F\u002F Таймаут для запитів (мс)\n        timeout: 10000,\n        \n        \u002F\u002F Функція для додавання заголовків до кожного запиту\n        prepareHeaders: (headers, { getState }) => {\n            \u002F\u002F Отримуємо токен авторизації зі стору\n            const token = (getState() as any).auth?.token\n            \n            if (token) {\n                headers.set('Authorization', `Bearer ${token}`)\n            }\n            \n            headers.set('Accept', 'application\u002Fjson')\n            headers.set('Content-Type', 'application\u002Fjson')\n            \n            return headers\n        },\n    }),\n    \n    \u002F\u002F 3️⃣ TAG TYPES: Типи сутностей для інвалідації кешу\n    tagTypes: ['Trip', 'User'],\n    \n    \u002F\u002F 4️⃣ REFETCH ON FOCUS: Оновлювати дані при поверненні в застосунок\n    refetchOnFocus: true,\n    \n    \u002F\u002F 5️⃣ REFETCH ON RECONNECT: Оновлювати при відновленні інтернету\n    refetchOnReconnect: true,\n    \n    \u002F\u002F 6️⃣ KEEP UNUSED DATA FOR: Скільки секунд зберігати невикористані дані\n    keepUnusedDataFor: 60,  \u002F\u002F 1 хвилина\n    \n    \u002F\u002F 7️⃣ ENDPOINTS: Опис API ендпоінтів\n    endpoints: (builder) => ({\n        getTrips: builder.query\u003CTrip[], void>({\n            query: () => '\u002Ftrips',\n        }),\n    }),\n})\n\nexport const { useGetTripsQuery } = tripsApi\n",[3829,11017,11018,11023,11041,11056,11068,11072,11077,11082,11087,11092,11097,11102,11107,11124,11129,11149,11156,11160,11164,11169,11192,11203,11231,11257,11261,11265,11270,11277,11281,11285,11293,11301,11309,11317,11325,11329,11333,11347,11352,11360,11364,11369,11377,11386,11391,11396,11406,11410,11415,11435,11440,11471,11475,11487,11517,11522,11526,11545,11563,11567,11573,11577,11581,11585,11590,11606,11610,11615,11625,11629,11634,11643,11647,11652,11666,11670,11675,11691,11711,11725,11729,11733,11737,11741],{"__ignoreMap":3827},[3832,11019,11020],{"class":3834,"line":3835},[3832,11021,11022],{"class":3838},"\u002F\u002F src\u002Fservices\u002FtripsApi.ts\n",[3832,11024,11025,11027,11029,11031,11033,11035,11037,11039],{"class":3834,"line":3842},[3832,11026,3846],{"class":3845},[3832,11028,3850],{"class":3849},[3832,11030,6153],{"class":3853},[3832,11032,3857],{"class":3849},[3832,11034,6158],{"class":3853},[3832,11036,3863],{"class":3849},[3832,11038,3866],{"class":3845},[3832,11040,6165],{"class":3869},[3832,11042,11043,11045,11047,11050,11052,11054],{"class":3834,"line":3873},[3832,11044,3846],{"class":3845},[3832,11046,3850],{"class":3849},[3832,11048,11049],{"class":3853},"Platform",[3832,11051,3863],{"class":3849},[3832,11053,3866],{"class":3845},[3832,11055,4652],{"class":3869},[3832,11057,11058,11060,11063,11065],{"class":3834,"line":3880},[3832,11059,3846],{"class":3845},[3832,11061,11062],{"class":3853}," Constants",[3832,11064,5856],{"class":3845},[3832,11066,11067],{"class":3869}," 'expo-constants'\n",[3832,11069,11070],{"class":3834,"line":3886},[3832,11071,3877],{"emptyLinePlaceholder":3876},[3832,11073,11074],{"class":3834,"line":3900},[3832,11075,11076],{"class":3838},"\u002F**\n",[3832,11078,11079],{"class":3834,"line":3912},[3832,11080,11081],{"class":3838}," * Функція для визначення правильної URL адреси в залежності від середовища.\n",[3832,11083,11084],{"class":3834,"line":3922},[3832,11085,11086],{"class":3838}," * Це критично для React Native, бо localhost працює по-різному:\n",[3832,11088,11089],{"class":3834,"line":3932},[3832,11090,11091],{"class":3838}," * - iOS Simulator: localhost = комп'ютер розробника\n",[3832,11093,11094],{"class":3834,"line":3942},[3832,11095,11096],{"class":3838}," * - Android Emulator: localhost = сам емулятор (потрібно 10.0.2.2)\n",[3832,11098,11099],{"class":3834,"line":3948},[3832,11100,11101],{"class":3838}," * - Реальний пристрій: потрібна IP-адреса комп'ютера в локальній мережі\n",[3832,11103,11104],{"class":3834,"line":3953},[3832,11105,11106],{"class":3838}," *\u002F\n",[3832,11108,11109,11111,11114,11117,11119,11122],{"class":3834,"line":3959},[3832,11110,4039],{"class":3889},[3832,11112,11113],{"class":4117}," getBaseUrl",[3832,11115,11116],{"class":3849}," = (): ",[3832,11118,4008],{"class":3893},[3832,11120,11121],{"class":3889}," =>",[3832,11123,3897],{"class":3849},[3832,11125,11126],{"class":3834,"line":3969},[3832,11127,11128],{"class":3838},"    \u002F\u002F Для Android емулятора використовуємо спеціальну адресу\n",[3832,11130,11131,11133,11135,11137,11139,11142,11144,11147],{"class":3834,"line":3986},[3832,11132,4821],{"class":3845},[3832,11134,4307],{"class":3849},[3832,11136,11049],{"class":3853},[3832,11138,4183],{"class":3849},[3832,11140,11141],{"class":4042},"OS",[3832,11143,5921],{"class":3849},[3832,11145,11146],{"class":3869},"'android'",[3832,11148,4189],{"class":3849},[3832,11150,11151,11153],{"class":3834,"line":4000},[3832,11152,4220],{"class":3845},[3832,11154,11155],{"class":3869}," 'http:\u002F\u002F10.0.2.2:3000'\n",[3832,11157,11158],{"class":3834,"line":4020},[3832,11159,4236],{"class":3849},[3832,11161,11162],{"class":3834,"line":4025},[3832,11163,4724],{"class":3849},[3832,11165,11166],{"class":3834,"line":4030},[3832,11167,11168],{"class":3838},"    \u002F\u002F Для реальних пристроїв отримуємо IP з Expo\n",[3832,11170,11171,11173,11176,11178,11181,11183,11186,11189],{"class":3834,"line":4036},[3832,11172,4710],{"class":3889},[3832,11174,11175],{"class":4042}," hostUri",[3832,11177,4114],{"class":3849},[3832,11179,11180],{"class":3853},"Constants",[3832,11182,4183],{"class":3849},[3832,11184,11185],{"class":3853},"expoConfig",[3832,11187,11188],{"class":3849},"?.",[3832,11190,11191],{"class":3853},"hostUri\n",[3832,11193,11194,11196,11198,11201],{"class":3834,"line":4054},[3832,11195,4821],{"class":3845},[3832,11197,4307],{"class":3849},[3832,11199,11200],{"class":3853},"hostUri",[3832,11202,4189],{"class":3849},[3832,11204,11205,11207,11210,11212,11214,11216,11219,11221,11224,11226,11229],{"class":3834,"line":4063},[3832,11206,4148],{"class":3889},[3832,11208,11209],{"class":4042}," ip",[3832,11211,4114],{"class":3849},[3832,11213,11200],{"class":3853},[3832,11215,4183],{"class":3849},[3832,11217,11218],{"class":4117},"split",[3832,11220,4162],{"class":3849},[3832,11222,11223],{"class":3869},"':'",[3832,11225,5621],{"class":3849},[3832,11227,11228],{"class":4117},"shift",[3832,11230,4230],{"class":3849},[3832,11232,11233,11235,11237,11240,11242,11244,11247,11250,11252,11254],{"class":3834,"line":4075},[3832,11234,4174],{"class":3845},[3832,11236,4307],{"class":3849},[3832,11238,11239],{"class":3853},"ip",[3832,11241,4313],{"class":3849},[3832,11243,6600],{"class":3845},[3832,11245,11246],{"class":3869}," `http:\u002F\u002F",[3832,11248,11249],{"class":3889},"${",[3832,11251,11239],{"class":3853},[3832,11253,4890],{"class":3889},[3832,11255,11256],{"class":3869},":3000`\n",[3832,11258,11259],{"class":3834,"line":4086},[3832,11260,4236],{"class":3849},[3832,11262,11263],{"class":3834,"line":4091},[3832,11264,4724],{"class":3849},[3832,11266,11267],{"class":3834,"line":4096},[3832,11268,11269],{"class":3838},"    \u002F\u002F Fallback для iOS Simulator\n",[3832,11271,11272,11274],{"class":3834,"line":4102},[3832,11273,4911],{"class":3845},[3832,11275,11276],{"class":3869}," 'http:\u002F\u002Flocalhost:3000'\n",[3832,11278,11279],{"class":3834,"line":4123},[3832,11280,3945],{"class":3849},[3832,11282,11283],{"class":3834,"line":4131},[3832,11284,3877],{"emptyLinePlaceholder":3876},[3832,11286,11287,11289,11291],{"class":3834,"line":4145},[3832,11288,3890],{"class":3889},[3832,11290,3894],{"class":3893},[3832,11292,3897],{"class":3849},[3832,11294,11295,11297,11299],{"class":3834,"line":4171},[3832,11296,3903],{"class":3853},[3832,11298,3906],{"class":3849},[3832,11300,3909],{"class":3893},[3832,11302,11303,11305,11307],{"class":3834,"line":4192},[3832,11304,3915],{"class":3853},[3832,11306,3906],{"class":3849},[3832,11308,3909],{"class":3893},[3832,11310,11311,11313,11315],{"class":3834,"line":4211},[3832,11312,3925],{"class":3853},[3832,11314,3906],{"class":3849},[3832,11316,3909],{"class":3893},[3832,11318,11319,11321,11323],{"class":3834,"line":4217},[3832,11320,3935],{"class":3853},[3832,11322,3906],{"class":3849},[3832,11324,3909],{"class":3893},[3832,11326,11327],{"class":3834,"line":4233},[3832,11328,3945],{"class":3849},[3832,11330,11331],{"class":3834,"line":4239},[3832,11332,3877],{"emptyLinePlaceholder":3876},[3832,11334,11335,11337,11339,11341,11343,11345],{"class":3834,"line":4244},[3832,11336,4105],{"class":3845},[3832,11338,4108],{"class":3889},[3832,11340,6231],{"class":4042},[3832,11342,4114],{"class":3849},[3832,11344,6153],{"class":4117},[3832,11346,4267],{"class":3849},[3832,11348,11349],{"class":3834,"line":4249},[3832,11350,11351],{"class":3838},"    \u002F\u002F 1️⃣ REDUCER PATH: Унікальне ім'я для Redux store\n",[3832,11353,11354,11356,11358],{"class":3834,"line":4255},[3832,11355,6242],{"class":3853},[3832,11357,6245],{"class":3869},[3832,11359,4072],{"class":3849},[3832,11361,11362],{"class":3834,"line":4270},[3832,11363,4724],{"class":3849},[3832,11365,11366],{"class":3834,"line":4281},[3832,11367,11368],{"class":3838},"    \u002F\u002F 2️⃣ BASE QUERY: Налаштування HTTP-клієнта\n",[3832,11370,11371,11373,11375],{"class":3834,"line":4289},[3832,11372,6252],{"class":3853},[3832,11374,6255],{"class":4117},[3832,11376,4267],{"class":3849},[3832,11378,11379,11381,11383],{"class":3834,"line":4298},[3832,11380,8895],{"class":3853},[3832,11382,11113],{"class":4117},[3832,11384,11385],{"class":3849},"(),\n",[3832,11387,11388],{"class":3834,"line":4320},[3832,11389,11390],{"class":3849},"        \n",[3832,11392,11393],{"class":3834,"line":4326},[3832,11394,11395],{"class":3838},"        \u002F\u002F Таймаут для запитів (мс)\n",[3832,11397,11398,11401,11404],{"class":3834,"line":4332},[3832,11399,11400],{"class":3853},"        timeout:",[3832,11402,11403],{"class":5726}," 10000",[3832,11405,4072],{"class":3849},[3832,11407,11408],{"class":3834,"line":4363},[3832,11409,11390],{"class":3849},[3832,11411,11412],{"class":3834,"line":4379},[3832,11413,11414],{"class":3838},"        \u002F\u002F Функція для додавання заголовків до кожного запиту\n",[3832,11416,11417,11419,11421,11423,11425,11427,11429,11431,11433],{"class":3834,"line":4394},[3832,11418,8905],{"class":4117},[3832,11420,4304],{"class":3853},[3832,11422,4307],{"class":3849},[3832,11424,8912],{"class":3853},[3832,11426,4611],{"class":3849},[3832,11428,9693],{"class":3853},[3832,11430,4981],{"class":3849},[3832,11432,4140],{"class":3889},[3832,11434,3897],{"class":3849},[3832,11436,11437],{"class":3834,"line":4400},[3832,11438,11439],{"class":3838},"            \u002F\u002F Отримуємо токен авторизації зі стору\n",[3832,11441,11442,11445,11448,11451,11453,11456,11458,11461,11463,11466,11468],{"class":3834,"line":4406},[3832,11443,11444],{"class":3889},"            const",[3832,11446,11447],{"class":4042}," token",[3832,11449,11450],{"class":3849}," = (",[3832,11452,9693],{"class":4117},[3832,11454,11455],{"class":3849},"() ",[3832,11457,6999],{"class":3845},[3832,11459,11460],{"class":3893}," any",[3832,11462,5621],{"class":3849},[3832,11464,11465],{"class":3853},"auth",[3832,11467,11188],{"class":3849},[3832,11469,11470],{"class":3853},"token\n",[3832,11472,11473],{"class":3834,"line":4437},[3832,11474,8518],{"class":3849},[3832,11476,11477,11480,11482,11485],{"class":3834,"line":4451},[3832,11478,11479],{"class":3845},"            if",[3832,11481,4307],{"class":3849},[3832,11483,11484],{"class":3853},"token",[3832,11486,4189],{"class":3849},[3832,11488,11489,11492,11494,11496,11498,11501,11503,11506,11508,11510,11512,11515],{"class":3834,"line":4470},[3832,11490,11491],{"class":3853},"                headers",[3832,11493,4183],{"class":3849},[3832,11495,8928],{"class":4117},[3832,11497,4162],{"class":3849},[3832,11499,11500],{"class":3869},"'Authorization'",[3832,11502,3857],{"class":3849},[3832,11504,11505],{"class":3869},"`Bearer ",[3832,11507,11249],{"class":3889},[3832,11509,11484],{"class":3853},[3832,11511,4890],{"class":3889},[3832,11513,11514],{"class":3869},"`",[3832,11516,4168],{"class":3849},[3832,11518,11519],{"class":3834,"line":4475},[3832,11520,11521],{"class":3849},"            }\n",[3832,11523,11524],{"class":3834,"line":4481},[3832,11525,8518],{"class":3849},[3832,11527,11528,11530,11532,11534,11536,11539,11541,11543],{"class":3834,"line":4511},[3832,11529,8923],{"class":3853},[3832,11531,4183],{"class":3849},[3832,11533,8928],{"class":4117},[3832,11535,4162],{"class":3849},[3832,11537,11538],{"class":3869},"'Accept'",[3832,11540,3857],{"class":3849},[3832,11542,8937],{"class":3869},[3832,11544,4168],{"class":3849},[3832,11546,11547,11549,11551,11553,11555,11557,11559,11561],{"class":3834,"line":4524},[3832,11548,8923],{"class":3853},[3832,11550,4183],{"class":3849},[3832,11552,8928],{"class":4117},[3832,11554,4162],{"class":3849},[3832,11556,5137],{"class":3869},[3832,11558,3857],{"class":3849},[3832,11560,8937],{"class":3869},[3832,11562,4168],{"class":3849},[3832,11564,11565],{"class":3834,"line":4552},[3832,11566,8518],{"class":3849},[3832,11568,11569,11571],{"class":3834,"line":4557},[3832,11570,8944],{"class":3845},[3832,11572,8947],{"class":3853},[3832,11574,11575],{"class":3834,"line":4563},[3832,11576,7069],{"class":3849},[3832,11578,11579],{"class":3834,"line":4569},[3832,11580,6475],{"class":3849},[3832,11582,11583],{"class":3834,"line":4574},[3832,11584,4724],{"class":3849},[3832,11586,11587],{"class":3834,"line":10534},[3832,11588,11589],{"class":3838},"    \u002F\u002F 3️⃣ TAG TYPES: Типи сутностей для інвалідації кешу\n",[3832,11591,11592,11594,11596,11598,11600,11603],{"class":3834,"line":10545},[3832,11593,6271],{"class":3853},[3832,11595,6274],{"class":3849},[3832,11597,6277],{"class":3869},[3832,11599,3857],{"class":3849},[3832,11601,11602],{"class":3869},"'User'",[3832,11604,11605],{"class":3849},"],\n",[3832,11607,11608],{"class":3834,"line":10554},[3832,11609,4724],{"class":3849},[3832,11611,11612],{"class":3834,"line":10564},[3832,11613,11614],{"class":3838},"    \u002F\u002F 4️⃣ REFETCH ON FOCUS: Оновлювати дані при поверненні в застосунок\n",[3832,11616,11617,11620,11623],{"class":3834,"line":10573},[3832,11618,11619],{"class":3853},"    refetchOnFocus:",[3832,11621,11622],{"class":3889}," true",[3832,11624,4072],{"class":3849},[3832,11626,11627],{"class":3834,"line":10583},[3832,11628,4724],{"class":3849},[3832,11630,11631],{"class":3834,"line":10593},[3832,11632,11633],{"class":3838},"    \u002F\u002F 5️⃣ REFETCH ON RECONNECT: Оновлювати при відновленні інтернету\n",[3832,11635,11636,11639,11641],{"class":3834,"line":10617},[3832,11637,11638],{"class":3853},"    refetchOnReconnect:",[3832,11640,11622],{"class":3889},[3832,11642,4072],{"class":3849},[3832,11644,11645],{"class":3834,"line":10628},[3832,11646,4724],{"class":3849},[3832,11648,11649],{"class":3834,"line":10639},[3832,11650,11651],{"class":3838},"    \u002F\u002F 6️⃣ KEEP UNUSED DATA FOR: Скільки секунд зберігати невикористані дані\n",[3832,11653,11654,11657,11660,11663],{"class":3834,"line":10650},[3832,11655,11656],{"class":3853},"    keepUnusedDataFor:",[3832,11658,11659],{"class":5726}," 60",[3832,11661,11662],{"class":3849},",  ",[3832,11664,11665],{"class":3838},"\u002F\u002F 1 хвилина\n",[3832,11667,11668],{"class":3834,"line":10655},[3832,11669,4724],{"class":3849},[3832,11671,11672],{"class":3834,"line":10663},[3832,11673,11674],{"class":3838},"    \u002F\u002F 7️⃣ ENDPOINTS: Опис API ендпоінтів\n",[3832,11676,11677,11679,11681,11683,11685,11687,11689],{"class":3834,"line":10672},[3832,11678,6288],{"class":4117},[3832,11680,4304],{"class":3853},[3832,11682,4307],{"class":3849},[3832,11684,4310],{"class":3853},[3832,11686,4313],{"class":3849},[3832,11688,4140],{"class":3889},[3832,11690,6301],{"class":3849},[3832,11692,11693,11695,11697,11699,11701,11703,11705,11707,11709],{"class":3834,"line":10683},[3832,11694,6311],{"class":3853},[3832,11696,6314],{"class":3853},[3832,11698,4183],{"class":3849},[3832,11700,6319],{"class":4117},[3832,11702,5084],{"class":3849},[3832,11704,3977],{"class":3893},[3832,11706,6326],{"class":3849},[3832,11708,6329],{"class":3893},[3832,11710,6332],{"class":3849},[3832,11712,11713,11715,11717,11719,11721,11723],{"class":3834,"line":10693},[3832,11714,6337],{"class":4117},[3832,11716,4304],{"class":3853},[3832,11718,4137],{"class":3849},[3832,11720,4140],{"class":3889},[3832,11722,6346],{"class":3869},[3832,11724,4072],{"class":3849},[3832,11726,11727],{"class":3834,"line":10704},[3832,11728,6367],{"class":3849},[3832,11730,11731],{"class":3834,"line":10709},[3832,11732,6475],{"class":3849},[3832,11734,11735],{"class":3834,"line":10717},[3832,11736,4566],{"class":3849},[3832,11738,11739],{"class":3834,"line":10726},[3832,11740,3877],{"emptyLinePlaceholder":3876},[3832,11742,11743,11745,11747,11749,11751,11753],{"class":3834,"line":10735},[3832,11744,4105],{"class":3845},[3832,11746,4108],{"class":3889},[3832,11748,3850],{"class":3849},[3832,11750,6499],{"class":4042},[3832,11752,4748],{"class":3849},[3832,11754,6509],{"class":3853},[3801,11756,11757],{},[3770,11758,11759],{},"Детальний розбір кожного параметра:",[8777,11761,11762,11862,12031,12108],{},[8780,11763,11765,11768,11840,11845],{"icon":132,"label":11764},"1️⃣ reducerPath — Ім'я слайса",[3801,11766,11767],{},"Це ім'я, під яким дані RTK Query зберігатимуться у Redux store.",[3822,11769,11771],{"className":3824,"code":11770,"language":3826,"meta":3827,"style":3827},"\u002F\u002F У store буде створено такий стан:\n{\n    tripsApi: {  \u002F\u002F ← ваш reducerPath\n        queries: { \u002F* закешовані дані *\u002F },\n        mutations: { \u002F* стани мутацій *\u002F },\n        subscriptions: { \u002F* активні підписки *\u002F }\n    }\n}\n",[3829,11772,11773,11778,11783,11794,11807,11819,11832,11836],{"__ignoreMap":3827},[3832,11774,11775],{"class":3834,"line":3835},[3832,11776,11777],{"class":3838},"\u002F\u002F У store буде створено такий стан:\n",[3832,11779,11780],{"class":3834,"line":3842},[3832,11781,11782],{"class":3849},"{\n",[3832,11784,11785,11788,11791],{"class":3834,"line":3873},[3832,11786,11787],{"class":5204},"    tripsApi",[3832,11789,11790],{"class":3849},": {  ",[3832,11792,11793],{"class":3838},"\u002F\u002F ← ваш reducerPath\n",[3832,11795,11796,11799,11802,11805],{"class":3834,"line":3880},[3832,11797,11798],{"class":5204},"        queries",[3832,11800,11801],{"class":3849},": { ",[3832,11803,11804],{"class":3838},"\u002F* закешовані дані *\u002F",[3832,11806,5145],{"class":3849},[3832,11808,11809,11812,11814,11817],{"class":3834,"line":3886},[3832,11810,11811],{"class":5204},"        mutations",[3832,11813,11801],{"class":3849},[3832,11815,11816],{"class":3838},"\u002F* стани мутацій *\u002F",[3832,11818,5145],{"class":3849},[3832,11820,11821,11824,11826,11829],{"class":3834,"line":3900},[3832,11822,11823],{"class":5204},"        subscriptions",[3832,11825,11801],{"class":3849},[3832,11827,11828],{"class":3838},"\u002F* активні підписки *\u002F",[3832,11830,11831],{"class":3849}," }\n",[3832,11833,11834],{"class":3834,"line":3912},[3832,11835,4236],{"class":3849},[3832,11837,11838],{"class":3834,"line":3922},[3832,11839,3945],{"class":3849},[3801,11841,11842],{},[3770,11843,11844],{},"Правила:",[3746,11846,11847,11850,11853,11859],{},[3749,11848,11849],{},"Має бути унікальним для кожного API",[3749,11851,11852],{},"Використовуйте camelCase",[3749,11854,11855,11856],{},"Якщо у вас один API на весь проєкт — можна назвати просто ",[3829,11857,11858],{},"'api'",[3749,11860,11861],{},"Якщо кілька API (наприклад, окремо для авторизації, платежів) — давайте описові назви",[8780,11863,11865,11873,11894,11899,11910],{"icon":1946,"label":11864},"2️⃣ baseQuery — HTTP-клієнт",[3801,11866,11867,11869,11870,11872],{},[3829,11868,6158],{}," — це вбудований HTTP-клієнт на основі ",[3829,11871,9459],{},". Він автоматично:",[3746,11874,11875,11882,11885,11888],{},[3749,11876,11877,11878,11881],{},"Додає ",[3829,11879,11880],{},"baseUrl"," до всіх запитів",[3749,11883,11884],{},"Обробляє JSON серіалізацію\u002Fдесеріалізацію",[3749,11886,11887],{},"Кидає помилки для статусів 4xx, 5xx",[3749,11889,11890,11891],{},"Підтримує кастомні заголовки через ",[3829,11892,11893],{},"prepareHeaders",[3801,11895,11896,11898],{},[3770,11897,11893],{}," викликається перед кожним запитом і дозволяє:",[3746,11900,11901,11904,11907],{},[3749,11902,11903],{},"Додати токени авторизації",[3749,11905,11906],{},"Встановити Content-Type",[3749,11908,11909],{},"Додати кастомні заголовки (версія API, мова інтерфейсу тощо)",[3822,11911,11913],{"className":3824,"code":11912,"language":3826,"meta":3827,"style":3827},"prepareHeaders: (headers, { getState, endpoint }) => {\n    \u002F\u002F Доступ до всього Redux state\n    const state = getState() as RootState\n    \n    \u002F\u002F Можна додавати різні токени для різних ендпоінтів\n    if (endpoint === 'getSecureData') {\n        headers.set('X-Special-Token', state.auth.specialToken)\n    }\n    \n    return headers\n}\n",[3829,11914,11915,11938,11943,11960,11964,11969,11984,12013,12017,12021,12027],{"__ignoreMap":3827},[3832,11916,11917,11919,11921,11923,11925,11927,11929,11932,11934,11936],{"class":3834,"line":3835},[3832,11918,11893],{"class":5204},[3832,11920,5208],{"class":3849},[3832,11922,8912],{"class":3853},[3832,11924,4611],{"class":3849},[3832,11926,9693],{"class":3853},[3832,11928,3857],{"class":3849},[3832,11930,11931],{"class":3853},"endpoint",[3832,11933,4981],{"class":3849},[3832,11935,4140],{"class":3889},[3832,11937,3897],{"class":3849},[3832,11939,11940],{"class":3834,"line":3842},[3832,11941,11942],{"class":3838},"    \u002F\u002F Доступ до всього Redux state\n",[3832,11944,11945,11947,11949,11951,11953,11955,11957],{"class":3834,"line":3873},[3832,11946,4710],{"class":3889},[3832,11948,4762],{"class":4042},[3832,11950,4114],{"class":3849},[3832,11952,9693],{"class":4117},[3832,11954,11455],{"class":3849},[3832,11956,6999],{"class":3845},[3832,11958,11959],{"class":3893}," RootState\n",[3832,11961,11962],{"class":3834,"line":3880},[3832,11963,4724],{"class":3849},[3832,11965,11966],{"class":3834,"line":3886},[3832,11967,11968],{"class":3838},"    \u002F\u002F Можна додавати різні токени для різних ендпоінтів\n",[3832,11970,11971,11973,11975,11977,11979,11982],{"class":3834,"line":3900},[3832,11972,4821],{"class":3845},[3832,11974,4307],{"class":3849},[3832,11976,11931],{"class":3853},[3832,11978,5921],{"class":3849},[3832,11980,11981],{"class":3869},"'getSecureData'",[3832,11983,4189],{"class":3849},[3832,11985,11986,11989,11991,11993,11995,11998,12000,12002,12004,12006,12008,12011],{"class":3834,"line":3912},[3832,11987,11988],{"class":3853},"        headers",[3832,11990,4183],{"class":3849},[3832,11992,8928],{"class":4117},[3832,11994,4162],{"class":3849},[3832,11996,11997],{"class":3869},"'X-Special-Token'",[3832,11999,3857],{"class":3849},[3832,12001,4354],{"class":3853},[3832,12003,4183],{"class":3849},[3832,12005,11465],{"class":3853},[3832,12007,4183],{"class":3849},[3832,12009,12010],{"class":3853},"specialToken",[3832,12012,4168],{"class":3849},[3832,12014,12015],{"class":3834,"line":3922},[3832,12016,4236],{"class":3849},[3832,12018,12019],{"class":3834,"line":3932},[3832,12020,4724],{"class":3849},[3832,12022,12023,12025],{"class":3834,"line":3942},[3832,12024,4911],{"class":3845},[3832,12026,8947],{"class":3853},[3832,12028,12029],{"class":3834,"line":3948},[3832,12030,3945],{"class":3849},[8780,12032,12035,12042,12047,12072],{"icon":12033,"label":12034},"i-lucide-tags","3️⃣ tagTypes — Система тегів для кешу",[3801,12036,12037,12038,12041],{},"Теги (",[3817,12039,12040],{},"tags",") — це ключова концепція RTK Query для автоматичної інвалідації кешу.",[3801,12043,12044],{},[3770,12045,12046],{},"Як це працює:",[12048,12049,12050,12060,12069],"ol",{},[3749,12051,12052,12053,12056,12057,9460],{},"Query ендпоінти ",[3770,12054,12055],{},"надають"," теги (",[3829,12058,12059],{},"providesTags",[3749,12061,12062,12063,12056,12066,9460],{},"Mutation ендпоінти ",[3770,12064,12065],{},"інвалідують",[3829,12067,12068],{},"invalidatesTags",[3749,12070,12071],{},"Коли тег інвалідується — всі запити з цим тегом автоматично перезавантажуються",[3822,12073,12075],{"className":3824,"code":12074,"language":3826,"meta":3827,"style":3827},"tagTypes: ['Trip', 'User', 'Comment']\n\n\u002F\u002F Детально розглянемо це у наступних розділах\n",[3829,12076,12077,12099,12103],{"__ignoreMap":3827},[3832,12078,12079,12082,12085,12087,12089,12091,12093,12096],{"class":3834,"line":3835},[3832,12080,12081],{"class":5204},"tagTypes",[3832,12083,12084],{"class":3849},": [",[3832,12086,6277],{"class":3869},[3832,12088,3857],{"class":3849},[3832,12090,11602],{"class":3869},[3832,12092,3857],{"class":3849},[3832,12094,12095],{"class":3869},"'Comment'",[3832,12097,12098],{"class":3849},"]\n",[3832,12100,12101],{"class":3834,"line":3842},[3832,12102,3877],{"emptyLinePlaceholder":3876},[3832,12104,12105],{"class":3834,"line":3873},[3832,12106,12107],{"class":3838},"\u002F\u002F Детально розглянемо це у наступних розділах\n",[8780,12109,12112,12117,12128,12133,12147],{"icon":12110,"label":12111},"i-lucide-focus","4️⃣ refetchOnFocus — Автооновлення при фокусі",[3801,12113,12114],{},[3770,12115,12116],{},"Мобільний сценарій:",[12048,12118,12119,12122,12125],{},[3749,12120,12121],{},"Користувач відкриває застосунок, бачить список поїздок",[3749,12123,12124],{},"Згортає застосунок (переходить в Instagram на 10 хвилин)",[3749,12126,12127],{},"Повертається назад",[3801,12129,12130],{},[3770,12131,12132],{},"Поведінка:",[3746,12134,12135,12141],{},[3749,12136,12137,12140],{},[3829,12138,12139],{},"refetchOnFocus: false"," — покаже старі дані (з кешу)",[3749,12142,12143,12146],{},[3829,12144,12145],{},"refetchOnFocus: true"," — автоматично оновить дані з сервера",[8569,12148,12149,12150,12156],{},"Для мобільних застосунків ",[3770,12151,12152,12153],{},"рекомендується ",[3829,12154,12155],{},"true",", бо користувачі часто перемикаються між додатками, і дані можуть застаріти.",[3801,12158,7400],{},[8780,12160,12163,12167,12178,12182],{"icon":12161,"label":12162},"i-lucide-wifi","5️⃣ refetchOnReconnect — Автооновлення при мережі",[3801,12164,12165],{},[3770,12166,12116],{},[12048,12168,12169,12172,12175],{},[3749,12170,12171],{},"Користувач їде в метро (втрачає інтернет)",[3749,12173,12174],{},"Застосунок показує закешовані дані",[3749,12176,12177],{},"Користувач виходить з метро (інтернет відновлюється)",[3801,12179,12180],{},[3770,12181,12132],{},[3746,12183,12184,12190],{},[3749,12185,12186,12189],{},[3829,12187,12188],{},"refetchOnReconnect: false"," — продовжує показувати старі дані",[3749,12191,12192,12195],{},[3829,12193,12194],{},"refetchOnReconnect: true"," — автоматично оновлює всі активні запити",[8780,12197,12200,12203,12208,12225,12230,12250,12255],{"icon":12198,"label":12199},"i-lucide-clock","6️⃣ keepUnusedDataFor — Час життя кешу",[3801,12201,12202],{},"Визначає скільки секунд зберігати дані після того, як жоден компонент їх не використовує.",[3801,12204,12205],{},[3770,12206,12207],{},"Приклад:",[3822,12209,12211],{"className":3824,"code":12210,"language":3826,"meta":3827,"style":3827},"keepUnusedDataFor: 60  \u002F\u002F 60 секунд = 1 хвилина\n",[3829,12212,12213],{"__ignoreMap":3827},[3832,12214,12215,12218,12220,12222],{"class":3834,"line":3835},[3832,12216,12217],{"class":5204},"keepUnusedDataFor",[3832,12219,3906],{"class":3849},[3832,12221,5733],{"class":5726},[3832,12223,12224],{"class":3838},"  \u002F\u002F 60 секунд = 1 хвилина\n",[3801,12226,12227],{},[3770,12228,12229],{},"Життєвий цикл:",[12048,12231,12232,12238,12241,12244,12247],{},[3749,12233,12234,12235,12237],{},"Користувач відкриває екран списку → ",[3829,12236,6751],{}," створює підписку",[3749,12239,12240],{},"Дані завантажуються і кешуються",[3749,12242,12243],{},"Користувач йде на інший екран → підписка видаляється",[3749,12245,12246],{},"Таймер запускається: через 60 секунд дані будуть видалені з пам'яті",[3749,12248,12249],{},"Якщо користувач повернеться на екран протягом 60 сек — дані будуть миттєво доступні з кешу!",[3801,12251,12252],{},[3770,12253,12254],{},"Рекомендації:",[3746,12256,12257,12264,12270],{},[3749,12258,12259,12260,12263],{},"Для часто використовуваних даних: ",[3829,12261,12262],{},"300"," (5 хвилин)",[3749,12265,12266,12267,12269],{},"Для рідко використовуваних: ",[3829,12268,5733],{}," (1 хвилина)",[3749,12271,12272,12273,12276],{},"Для критичних даних (профіль): ",[3829,12274,12275],{},"600"," (10 хвилин)",[3801,12278,7400],{},[3793,12280],{},[3796,12282,12284],{"id":12283},"авторизація-у-мобільному-застосунку","Авторизація у мобільному застосунку",[3801,12286,12287],{},"Більшість реальних застосунків потребують авторизації — користувач входить один раз, і застосунок запам'ятовує його. Давайте розберемо, як працює авторизація у мобільних додатках та як інтегрувати її з RTK Query.",[3809,12289,12291],{"id":12290},"базова-авторизація-додавання-токена-до-запитів","Базова авторизація: Додавання токена до запитів",[3801,12293,12294,12295,12297,12298,4183],{},"Найпростіший випадок — у вас є токен (",[3817,12296,11484],{},"), який потрібно відправляти з кожним запитом у заголовку ",[3829,12299,12300],{},"Authorization",[6852,12302,12304],{"id":12303},"крок-1-зберігаємо-токен-у-redux","Крок 1: Зберігаємо токен у Redux",[3801,12306,12307],{},"Спочатку створимо простий слайс для авторизації:",[3822,12309,12311],{"className":3824,"code":12310,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fstore\u002FauthSlice.ts\nimport { createSlice, PayloadAction } from '@reduxjs\u002Ftoolkit'\n\ninterface AuthState {\n    token: string | null\n    user: { id: string; email: string } | null\n}\n\nconst initialState: AuthState = {\n    token: null,\n    user: null,\n}\n\nconst authSlice = createSlice({\n    name: 'auth',\n    initialState,\n    reducers: {\n        \u002F\u002F Зберігаємо токен після успішного логіну\n        setCredentials: (state, action: PayloadAction\u003C{ token: string; user: any }>) => {\n            state.token = action.payload.token\n            state.user = action.payload.user\n        },\n        \u002F\u002F Видаляємо токен при виході\n        logout: (state) => {\n            state.token = null\n            state.user = null\n        },\n    },\n})\n\nexport const { setCredentials, logout } = authSlice.actions\nexport default authSlice.reducer\n",[3829,12312,12313,12318,12337,12341,12350,12363,12391,12395,12399,12412,12421,12430,12434,12438,12451,12460,12466,12472,12477,12522,12542,12563,12567,12572,12589,12601,12613,12617,12621,12625,12629,12655],{"__ignoreMap":3827},[3832,12314,12315],{"class":3834,"line":3835},[3832,12316,12317],{"class":3838},"\u002F\u002F src\u002Fstore\u002FauthSlice.ts\n",[3832,12319,12320,12322,12324,12326,12328,12331,12333,12335],{"class":3834,"line":3842},[3832,12321,3846],{"class":3845},[3832,12323,3850],{"class":3849},[3832,12325,3854],{"class":3853},[3832,12327,3857],{"class":3849},[3832,12329,12330],{"class":3853},"PayloadAction",[3832,12332,3863],{"class":3849},[3832,12334,3866],{"class":3845},[3832,12336,3870],{"class":3869},[3832,12338,12339],{"class":3834,"line":3873},[3832,12340,3877],{"emptyLinePlaceholder":3876},[3832,12342,12343,12345,12348],{"class":3834,"line":3880},[3832,12344,3890],{"class":3889},[3832,12346,12347],{"class":3893}," AuthState",[3832,12349,3897],{"class":3849},[3832,12351,12352,12355,12357,12359,12361],{"class":3834,"line":3886},[3832,12353,12354],{"class":3853},"    token",[3832,12356,3906],{"class":3849},[3832,12358,4008],{"class":3893},[3832,12360,4011],{"class":3849},[3832,12362,4391],{"class":3893},[3832,12364,12365,12368,12370,12372,12374,12376,12379,12382,12384,12386,12389],{"class":3834,"line":3900},[3832,12366,12367],{"class":3853},"    user",[3832,12369,11801],{"class":3849},[3832,12371,4962],{"class":3853},[3832,12373,3906],{"class":3849},[3832,12375,4008],{"class":3893},[3832,12377,12378],{"class":3849},"; ",[3832,12380,12381],{"class":3853},"email",[3832,12383,3906],{"class":3849},[3832,12385,4008],{"class":3893},[3832,12387,12388],{"class":3849}," } | ",[3832,12390,4391],{"class":3893},[3832,12392,12393],{"class":3834,"line":3912},[3832,12394,3945],{"class":3849},[3832,12396,12397],{"class":3834,"line":3922},[3832,12398,3877],{"emptyLinePlaceholder":3876},[3832,12400,12401,12403,12405,12407,12410],{"class":3834,"line":3932},[3832,12402,4039],{"class":3889},[3832,12404,4043],{"class":4042},[3832,12406,3906],{"class":3849},[3832,12408,12409],{"class":3893},"AuthState",[3832,12411,4051],{"class":3849},[3832,12413,12414,12417,12419],{"class":3834,"line":3942},[3832,12415,12416],{"class":3853},"    token:",[3832,12418,4081],{"class":3889},[3832,12420,4072],{"class":3849},[3832,12422,12423,12426,12428],{"class":3834,"line":3948},[3832,12424,12425],{"class":3853},"    user:",[3832,12427,4081],{"class":3889},[3832,12429,4072],{"class":3849},[3832,12431,12432],{"class":3834,"line":3953},[3832,12433,3945],{"class":3849},[3832,12435,12436],{"class":3834,"line":3959},[3832,12437,3877],{"emptyLinePlaceholder":3876},[3832,12439,12440,12442,12445,12447,12449],{"class":3834,"line":3969},[3832,12441,4039],{"class":3889},[3832,12443,12444],{"class":4042}," authSlice",[3832,12446,4114],{"class":3849},[3832,12448,3854],{"class":4117},[3832,12450,4267],{"class":3849},[3832,12452,12453,12455,12458],{"class":3834,"line":3986},[3832,12454,4273],{"class":3853},[3832,12456,12457],{"class":3869}," 'auth'",[3832,12459,4072],{"class":3849},[3832,12461,12462,12464],{"class":3834,"line":4000},[3832,12463,4284],{"class":3853},[3832,12465,4072],{"class":3849},[3832,12467,12468,12470],{"class":3834,"line":4020},[3832,12469,4292],{"class":3853},[3832,12471,3897],{"class":3849},[3832,12473,12474],{"class":3834,"line":4025},[3832,12475,12476],{"class":3838},"        \u002F\u002F Зберігаємо токен після успішного логіну\n",[3832,12478,12479,12482,12484,12486,12488,12490,12492,12494,12496,12499,12501,12503,12505,12507,12510,12512,12515,12518,12520],{"class":3834,"line":4030},[3832,12480,12481],{"class":4117},"        setCredentials",[3832,12483,4304],{"class":3853},[3832,12485,4307],{"class":3849},[3832,12487,4354],{"class":3853},[3832,12489,3857],{"class":3849},[3832,12491,4428],{"class":3853},[3832,12493,3906],{"class":3849},[3832,12495,12330],{"class":3893},[3832,12497,12498],{"class":3849},"\u003C{ ",[3832,12500,11484],{"class":3853},[3832,12502,3906],{"class":3849},[3832,12504,4008],{"class":3893},[3832,12506,12378],{"class":3849},[3832,12508,12509],{"class":3853},"user",[3832,12511,3906],{"class":3849},[3832,12513,12514],{"class":3893},"any",[3832,12516,12517],{"class":3849}," }>) ",[3832,12519,4140],{"class":3889},[3832,12521,3897],{"class":3849},[3832,12523,12524,12526,12528,12530,12532,12534,12536,12538,12540],{"class":3834,"line":4036},[3832,12525,5257],{"class":3853},[3832,12527,4183],{"class":3849},[3832,12529,11484],{"class":3853},[3832,12531,4114],{"class":3849},[3832,12533,4428],{"class":3853},[3832,12535,4183],{"class":3849},[3832,12537,5336],{"class":3853},[3832,12539,4183],{"class":3849},[3832,12541,11470],{"class":3853},[3832,12543,12544,12546,12548,12550,12552,12554,12556,12558,12560],{"class":3834,"line":4054},[3832,12545,5257],{"class":3853},[3832,12547,4183],{"class":3849},[3832,12549,12509],{"class":3853},[3832,12551,4114],{"class":3849},[3832,12553,4428],{"class":3853},[3832,12555,4183],{"class":3849},[3832,12557,5336],{"class":3853},[3832,12559,4183],{"class":3849},[3832,12561,12562],{"class":3853},"user\n",[3832,12564,12565],{"class":3834,"line":4063},[3832,12566,7069],{"class":3849},[3832,12568,12569],{"class":3834,"line":4075},[3832,12570,12571],{"class":3838},"        \u002F\u002F Видаляємо токен при виході\n",[3832,12573,12574,12577,12579,12581,12583,12585,12587],{"class":3834,"line":4086},[3832,12575,12576],{"class":4117},"        logout",[3832,12578,4304],{"class":3853},[3832,12580,4307],{"class":3849},[3832,12582,4354],{"class":3853},[3832,12584,4313],{"class":3849},[3832,12586,4140],{"class":3889},[3832,12588,3897],{"class":3849},[3832,12590,12591,12593,12595,12597,12599],{"class":3834,"line":4091},[3832,12592,5257],{"class":3853},[3832,12594,4183],{"class":3849},[3832,12596,11484],{"class":3853},[3832,12598,4114],{"class":3849},[3832,12600,4391],{"class":3889},[3832,12602,12603,12605,12607,12609,12611],{"class":3834,"line":4096},[3832,12604,5257],{"class":3853},[3832,12606,4183],{"class":3849},[3832,12608,12509],{"class":3853},[3832,12610,4114],{"class":3849},[3832,12612,4391],{"class":3889},[3832,12614,12615],{"class":3834,"line":4102},[3832,12616,7069],{"class":3849},[3832,12618,12619],{"class":3834,"line":4123},[3832,12620,4560],{"class":3849},[3832,12622,12623],{"class":3834,"line":4131},[3832,12624,4566],{"class":3849},[3832,12626,12627],{"class":3834,"line":4145},[3832,12628,3877],{"emptyLinePlaceholder":3876},[3832,12630,12631,12633,12635,12637,12640,12642,12645,12647,12650,12652],{"class":3834,"line":4171},[3832,12632,4105],{"class":3845},[3832,12634,4108],{"class":3889},[3832,12636,3850],{"class":3849},[3832,12638,12639],{"class":4042},"setCredentials",[3832,12641,3857],{"class":3849},[3832,12643,12644],{"class":4042},"logout",[3832,12646,4748],{"class":3849},[3832,12648,12649],{"class":3853},"authSlice",[3832,12651,4183],{"class":3849},[3832,12653,12654],{"class":3853},"actions\n",[3832,12656,12657,12659,12661,12663,12665],{"class":3834,"line":4192},[3832,12658,4105],{"class":3845},[3832,12660,4579],{"class":3845},[3832,12662,12444],{"class":3853},[3832,12664,4183],{"class":3849},[3832,12666,4586],{"class":3853},[6852,12668,12670],{"id":12669},"крок-2-налаштовуємо-prepareheaders","Крок 2: Налаштовуємо prepareHeaders",[3801,12672,12673],{},"Тепер змусимо RTK Query автоматично додавати токен до кожного запиту:",[3822,12675,12677],{"className":3824,"code":12676,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fservices\u002Fapi.ts\nimport { createApi, fetchBaseQuery } from '@reduxjs\u002Ftoolkit\u002Fquery\u002Freact'\nimport type { RootState } from '@\u002Fstore'\n\nexport const api = createApi({\n    baseQuery: fetchBaseQuery({\n        baseUrl: 'https:\u002F\u002Fapi.example.com',\n        \n        \u002F\u002F Функція викликається перед кожним запитом\n        prepareHeaders: (headers, { getState }) => {\n            \u002F\u002F Отримуємо токен зі Redux store\n            const token = (getState() as RootState).auth.token\n            \n            \u002F\u002F Якщо токен є — додаємо його до заголовків\n            if (token) {\n                headers.set('Authorization', `Bearer ${token}`)\n            }\n            \n            return headers\n        },\n    }),\n    endpoints: (builder) => ({\n        \u002F\u002F Тепер усі запити автоматично отримають заголовок Authorization\n        getProfile: builder.query({\n            query: () => '\u002Fuser\u002Fprofile',\n        }),\n        getTrips: builder.query({\n            query: () => '\u002Ftrips',\n        }),\n    }),\n})\n",[3829,12678,12679,12683,12701,12719,12723,12737,12745,12754,12758,12763,12783,12788,12812,12816,12821,12831,12857,12861,12865,12871,12875,12879,12895,12900,12913,12928,12932,12944,12958,12962,12966],{"__ignoreMap":3827},[3832,12680,12681],{"class":3834,"line":3835},[3832,12682,9193],{"class":3838},[3832,12684,12685,12687,12689,12691,12693,12695,12697,12699],{"class":3834,"line":3842},[3832,12686,3846],{"class":3845},[3832,12688,3850],{"class":3849},[3832,12690,6153],{"class":3853},[3832,12692,3857],{"class":3849},[3832,12694,6158],{"class":3853},[3832,12696,3863],{"class":3849},[3832,12698,3866],{"class":3845},[3832,12700,6165],{"class":3869},[3832,12702,12703,12705,12707,12709,12712,12714,12716],{"class":3834,"line":3873},[3832,12704,3846],{"class":3845},[3832,12706,9673],{"class":3845},[3832,12708,3850],{"class":3849},[3832,12710,12711],{"class":3853},"RootState",[3832,12713,3863],{"class":3849},[3832,12715,3866],{"class":3845},[3832,12717,12718],{"class":3869}," '@\u002Fstore'\n",[3832,12720,12721],{"class":3834,"line":3880},[3832,12722,3877],{"emptyLinePlaceholder":3876},[3832,12724,12725,12727,12729,12731,12733,12735],{"class":3834,"line":3886},[3832,12726,4105],{"class":3845},[3832,12728,4108],{"class":3889},[3832,12730,9277],{"class":4042},[3832,12732,4114],{"class":3849},[3832,12734,6153],{"class":4117},[3832,12736,4267],{"class":3849},[3832,12738,12739,12741,12743],{"class":3834,"line":3900},[3832,12740,6252],{"class":3853},[3832,12742,6255],{"class":4117},[3832,12744,4267],{"class":3849},[3832,12746,12747,12749,12752],{"class":3834,"line":3912},[3832,12748,8895],{"class":3853},[3832,12750,12751],{"class":3869}," 'https:\u002F\u002Fapi.example.com'",[3832,12753,4072],{"class":3849},[3832,12755,12756],{"class":3834,"line":3922},[3832,12757,11390],{"class":3849},[3832,12759,12760],{"class":3834,"line":3932},[3832,12761,12762],{"class":3838},"        \u002F\u002F Функція викликається перед кожним запитом\n",[3832,12764,12765,12767,12769,12771,12773,12775,12777,12779,12781],{"class":3834,"line":3942},[3832,12766,8905],{"class":4117},[3832,12768,4304],{"class":3853},[3832,12770,4307],{"class":3849},[3832,12772,8912],{"class":3853},[3832,12774,4611],{"class":3849},[3832,12776,9693],{"class":3853},[3832,12778,4981],{"class":3849},[3832,12780,4140],{"class":3889},[3832,12782,3897],{"class":3849},[3832,12784,12785],{"class":3834,"line":3948},[3832,12786,12787],{"class":3838},"            \u002F\u002F Отримуємо токен зі Redux store\n",[3832,12789,12790,12792,12794,12796,12798,12800,12802,12804,12806,12808,12810],{"class":3834,"line":3953},[3832,12791,11444],{"class":3889},[3832,12793,11447],{"class":4042},[3832,12795,11450],{"class":3849},[3832,12797,9693],{"class":4117},[3832,12799,11455],{"class":3849},[3832,12801,6999],{"class":3845},[3832,12803,9676],{"class":3893},[3832,12805,5621],{"class":3849},[3832,12807,11465],{"class":3853},[3832,12809,4183],{"class":3849},[3832,12811,11470],{"class":3853},[3832,12813,12814],{"class":3834,"line":3959},[3832,12815,8518],{"class":3849},[3832,12817,12818],{"class":3834,"line":3969},[3832,12819,12820],{"class":3838},"            \u002F\u002F Якщо токен є — додаємо його до заголовків\n",[3832,12822,12823,12825,12827,12829],{"class":3834,"line":3986},[3832,12824,11479],{"class":3845},[3832,12826,4307],{"class":3849},[3832,12828,11484],{"class":3853},[3832,12830,4189],{"class":3849},[3832,12832,12833,12835,12837,12839,12841,12843,12845,12847,12849,12851,12853,12855],{"class":3834,"line":4000},[3832,12834,11491],{"class":3853},[3832,12836,4183],{"class":3849},[3832,12838,8928],{"class":4117},[3832,12840,4162],{"class":3849},[3832,12842,11500],{"class":3869},[3832,12844,3857],{"class":3849},[3832,12846,11505],{"class":3869},[3832,12848,11249],{"class":3889},[3832,12850,11484],{"class":3853},[3832,12852,4890],{"class":3889},[3832,12854,11514],{"class":3869},[3832,12856,4168],{"class":3849},[3832,12858,12859],{"class":3834,"line":4020},[3832,12860,11521],{"class":3849},[3832,12862,12863],{"class":3834,"line":4025},[3832,12864,8518],{"class":3849},[3832,12866,12867,12869],{"class":3834,"line":4030},[3832,12868,8944],{"class":3845},[3832,12870,8947],{"class":3853},[3832,12872,12873],{"class":3834,"line":4036},[3832,12874,7069],{"class":3849},[3832,12876,12877],{"class":3834,"line":4054},[3832,12878,6475],{"class":3849},[3832,12880,12881,12883,12885,12887,12889,12891,12893],{"class":3834,"line":4063},[3832,12882,6288],{"class":4117},[3832,12884,4304],{"class":3853},[3832,12886,4307],{"class":3849},[3832,12888,4310],{"class":3853},[3832,12890,4313],{"class":3849},[3832,12892,4140],{"class":3889},[3832,12894,6301],{"class":3849},[3832,12896,12897],{"class":3834,"line":4075},[3832,12898,12899],{"class":3838},"        \u002F\u002F Тепер усі запити автоматично отримають заголовок Authorization\n",[3832,12901,12902,12905,12907,12909,12911],{"class":3834,"line":4086},[3832,12903,12904],{"class":3853},"        getProfile:",[3832,12906,6314],{"class":3853},[3832,12908,4183],{"class":3849},[3832,12910,6319],{"class":4117},[3832,12912,4267],{"class":3849},[3832,12914,12915,12917,12919,12921,12923,12926],{"class":3834,"line":4091},[3832,12916,6337],{"class":4117},[3832,12918,4304],{"class":3853},[3832,12920,4137],{"class":3849},[3832,12922,4140],{"class":3889},[3832,12924,12925],{"class":3869}," '\u002Fuser\u002Fprofile'",[3832,12927,4072],{"class":3849},[3832,12929,12930],{"class":3834,"line":4096},[3832,12931,6367],{"class":3849},[3832,12933,12934,12936,12938,12940,12942],{"class":3834,"line":4102},[3832,12935,6311],{"class":3853},[3832,12937,6314],{"class":3853},[3832,12939,4183],{"class":3849},[3832,12941,6319],{"class":4117},[3832,12943,4267],{"class":3849},[3832,12945,12946,12948,12950,12952,12954,12956],{"class":3834,"line":4123},[3832,12947,6337],{"class":4117},[3832,12949,4304],{"class":3853},[3832,12951,4137],{"class":3849},[3832,12953,4140],{"class":3889},[3832,12955,6346],{"class":3869},[3832,12957,4072],{"class":3849},[3832,12959,12960],{"class":3834,"line":4131},[3832,12961,6367],{"class":3849},[3832,12963,12964],{"class":3834,"line":4145},[3832,12965,6475],{"class":3849},[3832,12967,12968],{"class":3834,"line":4171},[3832,12969,4566],{"class":3849},[3801,12971,12972],{},[3770,12973,12974],{},"Що відбувається:",[5430,12976,12977,12981,12987,12991,12994,12998,13001,13005],{},[3809,12978,12980],{"id":12979},"користувач-логінитися","Користувач логінитися",[3801,12982,12983,12984],{},"Токен зберігається у Redux через ",[3829,12985,12986],{},"dispatch(setCredentials({ token, user }))",[3809,12988,12990],{"id":12989},"компонент-викликає-usegetprofilequery","Компонент викликає useGetProfileQuery()",[3801,12992,12993],{},"RTK Query готується виконати HTTP-запит",[3809,12995,12997],{"id":12996},"спрацьовує-prepareheaders","Спрацьовує prepareHeaders",[3801,12999,13000],{},"Функція читає токен зі стору та додає до заголовків",[3809,13002,13004],{"id":13003},"запит-відправляється","Запит відправляється",[3822,13006,13011],{"className":13007,"code":13009,"language":13010},[13008],"language-text","GET \u002Fuser\u002Fprofile\nAuthorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\n","text",[3829,13012,13009],{"__ignoreMap":3827},[3809,13014,13016],{"id":13015},"проблема-токен-застарів-401-unauthorized","Проблема: Токен застарів (401 Unauthorized)",[3801,13018,13019],{},"У реальних системах токени мають обмежений час життя. Типовий сценарій:",[3822,13021,13023],{"className":3824,"code":13022,"language":3826,"meta":3827,"style":3827},"\u002F\u002F Access Token живе 15 хвилин\n\u002F\u002F Користувач відкриває застосунок через 20 хвилин\n\n\u002F\u002F Запит повертає помилку:\n{\n    status: 401,\n    data: { message: \"Token expired\" }\n}\n",[3829,13024,13025,13030,13035,13039,13044,13048,13060,13076],{"__ignoreMap":3827},[3832,13026,13027],{"class":3834,"line":3835},[3832,13028,13029],{"class":3838},"\u002F\u002F Access Token живе 15 хвилин\n",[3832,13031,13032],{"class":3834,"line":3842},[3832,13033,13034],{"class":3838},"\u002F\u002F Користувач відкриває застосунок через 20 хвилин\n",[3832,13036,13037],{"class":3834,"line":3873},[3832,13038,3877],{"emptyLinePlaceholder":3876},[3832,13040,13041],{"class":3834,"line":3880},[3832,13042,13043],{"class":3838},"\u002F\u002F Запит повертає помилку:\n",[3832,13045,13046],{"class":3834,"line":3886},[3832,13047,11782],{"class":3849},[3832,13049,13050,13053,13055,13058],{"class":3834,"line":3900},[3832,13051,13052],{"class":5204},"    status",[3832,13054,3906],{"class":3849},[3832,13056,13057],{"class":5726},"401",[3832,13059,4072],{"class":3849},[3832,13061,13062,13065,13067,13069,13071,13074],{"class":3834,"line":3912},[3832,13063,13064],{"class":5204},"    data",[3832,13066,11801],{"class":3849},[3832,13068,4543],{"class":5204},[3832,13070,3906],{"class":3849},[3832,13072,13073],{"class":3869},"\"Token expired\"",[3832,13075,11831],{"class":3849},[3832,13077,13078],{"class":3834,"line":3922},[3832,13079,3945],{"class":3849},[3801,13081,13082,13083,13086],{},"Наївне рішення — попросити користувача ввести пароль знову. Але це ",[3770,13084,13085],{},"жахливий UX"," для мобільного застосунку!",[3809,13088,13090],{"id":13089},"рішення-refresh-token-pattern","Рішення: Refresh Token Pattern",[3801,13092,13093,13094,4304],{},"Сучасні API використовують ",[3770,13095,13096],{},"дві пари токенів",[6860,13098,13099,13160],{},[3822,13100,13103],{"className":3824,"code":13101,"filename":13102,"language":3826,"meta":3827,"style":3827},"\u002F\u002F Живе 15-30 хвилин\n\u002F\u002F Використовується для звичайних запитів\n{\n    \"type\": \"access\",\n    \"token\": \"eyJhbGc...\",\n    \"expiresIn\": 900  \u002F\u002F 15 хвилин у секундах\n}\n","Access Token (короткоживучий)",[3829,13104,13105,13110,13115,13119,13131,13143,13156],{"__ignoreMap":3827},[3832,13106,13107],{"class":3834,"line":3835},[3832,13108,13109],{"class":3838},"\u002F\u002F Живе 15-30 хвилин\n",[3832,13111,13112],{"class":3834,"line":3842},[3832,13113,13114],{"class":3838},"\u002F\u002F Використовується для звичайних запитів\n",[3832,13116,13117],{"class":3834,"line":3873},[3832,13118,11782],{"class":3849},[3832,13120,13121,13124,13126,13129],{"class":3834,"line":3880},[3832,13122,13123],{"class":3869},"    \"type\"",[3832,13125,3906],{"class":3849},[3832,13127,13128],{"class":3869},"\"access\"",[3832,13130,4072],{"class":3849},[3832,13132,13133,13136,13138,13141],{"class":3834,"line":3886},[3832,13134,13135],{"class":3869},"    \"token\"",[3832,13137,3906],{"class":3849},[3832,13139,13140],{"class":3869},"\"eyJhbGc...\"",[3832,13142,4072],{"class":3849},[3832,13144,13145,13148,13150,13153],{"class":3834,"line":3900},[3832,13146,13147],{"class":3869},"    \"expiresIn\"",[3832,13149,3906],{"class":3849},[3832,13151,13152],{"class":5726},"900",[3832,13154,13155],{"class":3838},"  \u002F\u002F 15 хвилин у секундах\n",[3832,13157,13158],{"class":3834,"line":3912},[3832,13159,3945],{"class":3849},[3822,13161,13164],{"className":3824,"code":13162,"filename":13163,"language":3826,"meta":3827,"style":3827},"\u002F\u002F Живе 7-30 днів\n\u002F\u002F Використовується ТІЛЬКИ для отримання нового Access Token\n{\n    \"type\": \"refresh\",\n    \"token\": \"dGhpcyBpcyByZWZyZXNo...\",\n    \"expiresIn\": 2592000  \u002F\u002F 30 днів\n}\n","Refresh Token (довгоживучий)",[3829,13165,13166,13171,13176,13180,13191,13202,13214],{"__ignoreMap":3827},[3832,13167,13168],{"class":3834,"line":3835},[3832,13169,13170],{"class":3838},"\u002F\u002F Живе 7-30 днів\n",[3832,13172,13173],{"class":3834,"line":3842},[3832,13174,13175],{"class":3838},"\u002F\u002F Використовується ТІЛЬКИ для отримання нового Access Token\n",[3832,13177,13178],{"class":3834,"line":3873},[3832,13179,11782],{"class":3849},[3832,13181,13182,13184,13186,13189],{"class":3834,"line":3880},[3832,13183,13123],{"class":3869},[3832,13185,3906],{"class":3849},[3832,13187,13188],{"class":3869},"\"refresh\"",[3832,13190,4072],{"class":3849},[3832,13192,13193,13195,13197,13200],{"class":3834,"line":3886},[3832,13194,13135],{"class":3869},[3832,13196,3906],{"class":3849},[3832,13198,13199],{"class":3869},"\"dGhpcyBpcyByZWZyZXNo...\"",[3832,13201,4072],{"class":3849},[3832,13203,13204,13206,13208,13211],{"class":3834,"line":3900},[3832,13205,13147],{"class":3869},[3832,13207,3906],{"class":3849},[3832,13209,13210],{"class":5726},"2592000",[3832,13212,13213],{"class":3838},"  \u002F\u002F 30 днів\n",[3832,13215,13216],{"class":3834,"line":3912},[3832,13217,3945],{"class":3849},[3801,13219,13220],{},[3770,13221,13222],{},"Логіка роботи:",[8090,13224,13226],{"alt":13225},"JWT Refresh Token Flow",[3822,13227,13229],{"className":8095,"code":13228,"language":8097,"meta":3827,"style":3827},"@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\nskinparam defaultFontName \"Helvetica\"\n\nactor \"Користувач\" as User #DBEAFE\nparticipant \"Mobile App\" as App #DCFCE7\nparticipant \"RTK Query\" as RTK #FED7AA\nparticipant \"Backend API\" as API #FECACA\n\n== Початковий логін ==\nUser -> App : Вводить email + пароль\nApp -> API : POST \u002Fauth\u002Flogin\nAPI --> App : { accessToken, refreshToken }\nApp -> App : Зберігає обидва токени у Redux\n\n== Звичайний запит (токен валідний) ==\nUser -> App : Відкриває список поїздок\nApp -> RTK : useGetTripsQuery()\nRTK -> API : GET \u002Ftrips\\nAuthorization: Bearer \u003CaccessToken>\nAPI --> RTK : 200 OK + дані\nRTK --> App : Показує список\n\n== Запит з застарілим токеном ==\nUser -> App : Відкриває профіль (через 20 хвилин)\nApp -> RTK : useGetProfileQuery()\nRTK -> API : GET \u002Fprofile\\nAuthorization: Bearer \u003Cстарий accessToken>\nAPI --> RTK : ❌ 401 Unauthorized\n\nRTK -> RTK : Перехоплюємо помилку 401\nRTK -> API : POST \u002Fauth\u002Frefresh\\n{ refreshToken }\nAPI --> RTK : ✅ { newAccessToken, newRefreshToken }\nRTK -> RTK : Оновлюємо токени у Redux\n\nRTK -> API : Повторний запит GET \u002Fprofile\\nAuthorization: Bearer \u003CНОВИЙ accessToken>\nAPI --> RTK : 200 OK + дані профілю\nRTK --> App : Показує профіль\nnote over User, App #FEF3C7\n    Користувач навіть не помітив,\n    що токен оновлювався!\nend note\n\n@enduml\n",[3829,13230,13231,13235,13239,13243,13247,13251,13256,13261,13266,13271,13275,13280,13285,13290,13295,13300,13304,13309,13314,13319,13324,13329,13334,13338,13343,13348,13353,13358,13363,13367,13372,13377,13382,13387,13391,13396,13401,13406,13411,13416,13421,13426,13430],{"__ignoreMap":3827},[3832,13232,13233],{"class":3834,"line":3835},[3832,13234,8104],{},[3832,13236,13237],{"class":3834,"line":3842},[3832,13238,8109],{},[3832,13240,13241],{"class":3834,"line":3873},[3832,13242,8114],{},[3832,13244,13245],{"class":3834,"line":3880},[3832,13246,8119],{},[3832,13248,13249],{"class":3834,"line":3886},[3832,13250,3877],{"emptyLinePlaceholder":3876},[3832,13252,13253],{"class":3834,"line":3900},[3832,13254,13255],{},"actor \"Користувач\" as User #DBEAFE\n",[3832,13257,13258],{"class":3834,"line":3912},[3832,13259,13260],{},"participant \"Mobile App\" as App #DCFCE7\n",[3832,13262,13263],{"class":3834,"line":3922},[3832,13264,13265],{},"participant \"RTK Query\" as RTK #FED7AA\n",[3832,13267,13268],{"class":3834,"line":3932},[3832,13269,13270],{},"participant \"Backend API\" as API #FECACA\n",[3832,13272,13273],{"class":3834,"line":3942},[3832,13274,3877],{"emptyLinePlaceholder":3876},[3832,13276,13277],{"class":3834,"line":3948},[3832,13278,13279],{},"== Початковий логін ==\n",[3832,13281,13282],{"class":3834,"line":3953},[3832,13283,13284],{},"User -> App : Вводить email + пароль\n",[3832,13286,13287],{"class":3834,"line":3959},[3832,13288,13289],{},"App -> API : POST \u002Fauth\u002Flogin\n",[3832,13291,13292],{"class":3834,"line":3969},[3832,13293,13294],{},"API --> App : { accessToken, refreshToken }\n",[3832,13296,13297],{"class":3834,"line":3986},[3832,13298,13299],{},"App -> App : Зберігає обидва токени у Redux\n",[3832,13301,13302],{"class":3834,"line":4000},[3832,13303,3877],{"emptyLinePlaceholder":3876},[3832,13305,13306],{"class":3834,"line":4020},[3832,13307,13308],{},"== Звичайний запит (токен валідний) ==\n",[3832,13310,13311],{"class":3834,"line":4025},[3832,13312,13313],{},"User -> App : Відкриває список поїздок\n",[3832,13315,13316],{"class":3834,"line":4030},[3832,13317,13318],{},"App -> RTK : useGetTripsQuery()\n",[3832,13320,13321],{"class":3834,"line":4036},[3832,13322,13323],{},"RTK -> API : GET \u002Ftrips\\nAuthorization: Bearer \u003CaccessToken>\n",[3832,13325,13326],{"class":3834,"line":4054},[3832,13327,13328],{},"API --> RTK : 200 OK + дані\n",[3832,13330,13331],{"class":3834,"line":4063},[3832,13332,13333],{},"RTK --> App : Показує список\n",[3832,13335,13336],{"class":3834,"line":4075},[3832,13337,3877],{"emptyLinePlaceholder":3876},[3832,13339,13340],{"class":3834,"line":4086},[3832,13341,13342],{},"== Запит з застарілим токеном ==\n",[3832,13344,13345],{"class":3834,"line":4091},[3832,13346,13347],{},"User -> App : Відкриває профіль (через 20 хвилин)\n",[3832,13349,13350],{"class":3834,"line":4096},[3832,13351,13352],{},"App -> RTK : useGetProfileQuery()\n",[3832,13354,13355],{"class":3834,"line":4102},[3832,13356,13357],{},"RTK -> API : GET \u002Fprofile\\nAuthorization: Bearer \u003Cстарий accessToken>\n",[3832,13359,13360],{"class":3834,"line":4123},[3832,13361,13362],{},"API --> RTK : ❌ 401 Unauthorized\n",[3832,13364,13365],{"class":3834,"line":4131},[3832,13366,3877],{"emptyLinePlaceholder":3876},[3832,13368,13369],{"class":3834,"line":4145},[3832,13370,13371],{},"RTK -> RTK : Перехоплюємо помилку 401\n",[3832,13373,13374],{"class":3834,"line":4171},[3832,13375,13376],{},"RTK -> API : POST \u002Fauth\u002Frefresh\\n{ refreshToken }\n",[3832,13378,13379],{"class":3834,"line":4192},[3832,13380,13381],{},"API --> RTK : ✅ { newAccessToken, newRefreshToken }\n",[3832,13383,13384],{"class":3834,"line":4211},[3832,13385,13386],{},"RTK -> RTK : Оновлюємо токени у Redux\n",[3832,13388,13389],{"class":3834,"line":4217},[3832,13390,3877],{"emptyLinePlaceholder":3876},[3832,13392,13393],{"class":3834,"line":4233},[3832,13394,13395],{},"RTK -> API : Повторний запит GET \u002Fprofile\\nAuthorization: Bearer \u003CНОВИЙ accessToken>\n",[3832,13397,13398],{"class":3834,"line":4239},[3832,13399,13400],{},"API --> RTK : 200 OK + дані профілю\n",[3832,13402,13403],{"class":3834,"line":4244},[3832,13404,13405],{},"RTK --> App : Показує профіль\n",[3832,13407,13408],{"class":3834,"line":4249},[3832,13409,13410],{},"note over User, App #FEF3C7\n",[3832,13412,13413],{"class":3834,"line":4255},[3832,13414,13415],{},"    Користувач навіть не помітив,\n",[3832,13417,13418],{"class":3834,"line":4270},[3832,13419,13420],{},"    що токен оновлювався!\n",[3832,13422,13423],{"class":3834,"line":4281},[3832,13424,13425],{},"end note\n",[3832,13427,13428],{"class":3834,"line":4289},[3832,13429,3877],{"emptyLinePlaceholder":3876},[3832,13431,13432],{"class":3834,"line":4298},[3832,13433,8288],{},[3809,13435,13437],{"id":13436},"реалізація-автоматичне-оновлення-токенів","Реалізація: Автоматичне оновлення токенів",[3801,13439,13440],{},"Тепер напишемо код, який автоматично обробляє цю логіку:",[3822,13442,13444],{"className":3824,"code":13443,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fservices\u002FbaseQueryWithReauth.ts\nimport { fetchBaseQuery } from '@reduxjs\u002Ftoolkit\u002Fquery'\nimport type { BaseQueryFn, FetchArgs, FetchBaseQueryError } from '@reduxjs\u002Ftoolkit\u002Fquery'\nimport { setCredentials, logout } from '@\u002Fstore\u002FauthSlice'\nimport type { RootState } from '@\u002Fstore'\n\n\u002F\u002F Базовий запит з токеном\nconst baseQuery = fetchBaseQuery({\n    baseUrl: 'https:\u002F\u002Fapi.example.com',\n    prepareHeaders: (headers, { getState }) => {\n        const token = (getState() as RootState).auth.token\n        if (token) {\n            headers.set('Authorization', `Bearer ${token}`)\n        }\n        return headers\n    },\n})\n\n\u002F\u002F Обгортка, яка додає логіку refresh\nexport const baseQueryWithReauth: BaseQueryFn\u003C\n    string | FetchArgs,\n    unknown,\n    FetchBaseQueryError\n> = async (args, api, extraOptions) => {\n    \u002F\u002F Спробуємо виконати звичайний запит\n    let result = await baseQuery(args, api, extraOptions)\n\n    \u002F\u002F Якщо отримали 401 — токен застарів\n    if (result.error && result.error.status === 401) {\n        console.log('🔄 Access token застарів, оновлюємо...')\n        \n        \u002F\u002F Отримуємо refresh token зі стору\n        const refreshToken = (api.getState() as RootState).auth.refreshToken\n        \n        \u002F\u002F Запитуємо новий access token\n        const refreshResult = await baseQuery(\n            {\n                url: '\u002Fauth\u002Frefresh',\n                method: 'POST',\n                body: { refreshToken },\n            },\n            api,\n            extraOptions,\n        )\n\n        if (refreshResult.data) {\n            \u002F\u002F ✅ Успішно оновили токен\n            console.log('✅ Токен оновлено успішно')\n            \n            \u002F\u002F Зберігаємо нові токени у Redux\n            api.dispatch(setCredentials(refreshResult.data as any))\n            \n            \u002F\u002F Повторюємо початковий запит з новим токеном\n            result = await baseQuery(args, api, extraOptions)\n        } else {\n            \u002F\u002F ❌ Не вдалося оновити токен — розлогінюємо користувача\n            console.log('❌ Не вдалося оновити токен, виходимо')\n            api.dispatch(logout())\n        }\n    }\n\n    return result\n}\n",[3829,13445,13446,13451,13465,13492,13511,13527,13531,13536,13549,13558,13579,13603,13613,13639,13643,13649,13653,13657,13661,13666,13682,13693,13700,13705,13732,13737,13765,13769,13774,13807,13823,13827,13832,13862,13866,13871,13886,13891,13900,13908,13919,13924,13931,13938,13942,13946,13961,13966,13982,13986,13991,14018,14022,14027,14052,14062,14067,14082,14096,14100,14104,14108,14115],{"__ignoreMap":3827},[3832,13447,13448],{"class":3834,"line":3835},[3832,13449,13450],{"class":3838},"\u002F\u002F src\u002Fservices\u002FbaseQueryWithReauth.ts\n",[3832,13452,13453,13455,13457,13459,13461,13463],{"class":3834,"line":3842},[3832,13454,3846],{"class":3845},[3832,13456,3850],{"class":3849},[3832,13458,6158],{"class":3853},[3832,13460,3863],{"class":3849},[3832,13462,3866],{"class":3845},[3832,13464,9525],{"class":3869},[3832,13466,13467,13469,13471,13473,13476,13478,13481,13483,13486,13488,13490],{"class":3834,"line":3873},[3832,13468,3846],{"class":3845},[3832,13470,9673],{"class":3845},[3832,13472,3850],{"class":3849},[3832,13474,13475],{"class":3853},"BaseQueryFn",[3832,13477,3857],{"class":3849},[3832,13479,13480],{"class":3853},"FetchArgs",[3832,13482,3857],{"class":3849},[3832,13484,13485],{"class":3853},"FetchBaseQueryError",[3832,13487,3863],{"class":3849},[3832,13489,3866],{"class":3845},[3832,13491,9525],{"class":3869},[3832,13493,13494,13496,13498,13500,13502,13504,13506,13508],{"class":3834,"line":3880},[3832,13495,3846],{"class":3845},[3832,13497,3850],{"class":3849},[3832,13499,12639],{"class":3853},[3832,13501,3857],{"class":3849},[3832,13503,12644],{"class":3853},[3832,13505,3863],{"class":3849},[3832,13507,3866],{"class":3845},[3832,13509,13510],{"class":3869}," '@\u002Fstore\u002FauthSlice'\n",[3832,13512,13513,13515,13517,13519,13521,13523,13525],{"class":3834,"line":3886},[3832,13514,3846],{"class":3845},[3832,13516,9673],{"class":3845},[3832,13518,3850],{"class":3849},[3832,13520,12711],{"class":3853},[3832,13522,3863],{"class":3849},[3832,13524,3866],{"class":3845},[3832,13526,12718],{"class":3869},[3832,13528,13529],{"class":3834,"line":3900},[3832,13530,3877],{"emptyLinePlaceholder":3876},[3832,13532,13533],{"class":3834,"line":3912},[3832,13534,13535],{"class":3838},"\u002F\u002F Базовий запит з токеном\n",[3832,13537,13538,13540,13543,13545,13547],{"class":3834,"line":3922},[3832,13539,4039],{"class":3889},[3832,13541,13542],{"class":4042}," baseQuery",[3832,13544,4114],{"class":3849},[3832,13546,6158],{"class":4117},[3832,13548,4267],{"class":3849},[3832,13550,13551,13554,13556],{"class":3834,"line":3932},[3832,13552,13553],{"class":3853},"    baseUrl:",[3832,13555,12751],{"class":3869},[3832,13557,4072],{"class":3849},[3832,13559,13560,13563,13565,13567,13569,13571,13573,13575,13577],{"class":3834,"line":3942},[3832,13561,13562],{"class":4117},"    prepareHeaders",[3832,13564,4304],{"class":3853},[3832,13566,4307],{"class":3849},[3832,13568,8912],{"class":3853},[3832,13570,4611],{"class":3849},[3832,13572,9693],{"class":3853},[3832,13574,4981],{"class":3849},[3832,13576,4140],{"class":3889},[3832,13578,3897],{"class":3849},[3832,13580,13581,13583,13585,13587,13589,13591,13593,13595,13597,13599,13601],{"class":3834,"line":3948},[3832,13582,4148],{"class":3889},[3832,13584,11447],{"class":4042},[3832,13586,11450],{"class":3849},[3832,13588,9693],{"class":4117},[3832,13590,11455],{"class":3849},[3832,13592,6999],{"class":3845},[3832,13594,9676],{"class":3893},[3832,13596,5621],{"class":3849},[3832,13598,11465],{"class":3853},[3832,13600,4183],{"class":3849},[3832,13602,11470],{"class":3853},[3832,13604,13605,13607,13609,13611],{"class":3834,"line":3953},[3832,13606,4174],{"class":3845},[3832,13608,4307],{"class":3849},[3832,13610,11484],{"class":3853},[3832,13612,4189],{"class":3849},[3832,13614,13615,13617,13619,13621,13623,13625,13627,13629,13631,13633,13635,13637],{"class":3834,"line":3959},[3832,13616,8923],{"class":3853},[3832,13618,4183],{"class":3849},[3832,13620,8928],{"class":4117},[3832,13622,4162],{"class":3849},[3832,13624,11500],{"class":3869},[3832,13626,3857],{"class":3849},[3832,13628,11505],{"class":3869},[3832,13630,11249],{"class":3889},[3832,13632,11484],{"class":3853},[3832,13634,4890],{"class":3889},[3832,13636,11514],{"class":3869},[3832,13638,4168],{"class":3849},[3832,13640,13641],{"class":3834,"line":3969},[3832,13642,4214],{"class":3849},[3832,13644,13645,13647],{"class":3834,"line":3986},[3832,13646,4220],{"class":3845},[3832,13648,8947],{"class":3853},[3832,13650,13651],{"class":3834,"line":4000},[3832,13652,4560],{"class":3849},[3832,13654,13655],{"class":3834,"line":4020},[3832,13656,4566],{"class":3849},[3832,13658,13659],{"class":3834,"line":4025},[3832,13660,3877],{"emptyLinePlaceholder":3876},[3832,13662,13663],{"class":3834,"line":4030},[3832,13664,13665],{"class":3838},"\u002F\u002F Обгортка, яка додає логіку refresh\n",[3832,13667,13668,13670,13672,13675,13677,13679],{"class":3834,"line":4036},[3832,13669,4105],{"class":3845},[3832,13671,4108],{"class":3889},[3832,13673,13674],{"class":4042}," baseQueryWithReauth",[3832,13676,3906],{"class":3849},[3832,13678,13475],{"class":3893},[3832,13680,13681],{"class":3849},"\u003C\n",[3832,13683,13684,13687,13689,13691],{"class":3834,"line":4054},[3832,13685,13686],{"class":3893},"    string",[3832,13688,4011],{"class":3849},[3832,13690,13480],{"class":3893},[3832,13692,4072],{"class":3849},[3832,13694,13695,13698],{"class":3834,"line":4063},[3832,13696,13697],{"class":3893},"    unknown",[3832,13699,4072],{"class":3849},[3832,13701,13702],{"class":3834,"line":4075},[3832,13703,13704],{"class":3893},"    FetchBaseQueryError\n",[3832,13706,13707,13710,13712,13714,13717,13719,13721,13723,13726,13728,13730],{"class":3834,"line":4086},[3832,13708,13709],{"class":3849},"> = ",[3832,13711,5477],{"class":3889},[3832,13713,4307],{"class":3849},[3832,13715,13716],{"class":3853},"args",[3832,13718,3857],{"class":3849},[3832,13720,9534],{"class":3853},[3832,13722,3857],{"class":3849},[3832,13724,13725],{"class":3853},"extraOptions",[3832,13727,4313],{"class":3849},[3832,13729,4140],{"class":3889},[3832,13731,3897],{"class":3849},[3832,13733,13734],{"class":3834,"line":4091},[3832,13735,13736],{"class":3838},"    \u002F\u002F Спробуємо виконати звичайний запит\n",[3832,13738,13739,13742,13745,13747,13749,13751,13753,13755,13757,13759,13761,13763],{"class":3834,"line":4096},[3832,13740,13741],{"class":3889},"    let",[3832,13743,13744],{"class":3853}," result",[3832,13746,4114],{"class":3849},[3832,13748,4156],{"class":3845},[3832,13750,13542],{"class":4117},[3832,13752,4162],{"class":3849},[3832,13754,13716],{"class":3853},[3832,13756,3857],{"class":3849},[3832,13758,9534],{"class":3853},[3832,13760,3857],{"class":3849},[3832,13762,13725],{"class":3853},[3832,13764,4168],{"class":3849},[3832,13766,13767],{"class":3834,"line":4102},[3832,13768,3877],{"emptyLinePlaceholder":3876},[3832,13770,13771],{"class":3834,"line":4123},[3832,13772,13773],{"class":3838},"    \u002F\u002F Якщо отримали 401 — токен застарів\n",[3832,13775,13776,13778,13780,13783,13785,13787,13790,13792,13794,13796,13798,13801,13803,13805],{"class":3834,"line":4131},[3832,13777,4821],{"class":3845},[3832,13779,4307],{"class":3849},[3832,13781,13782],{"class":3853},"result",[3832,13784,4183],{"class":3849},[3832,13786,4386],{"class":3853},[3832,13788,13789],{"class":3849}," && ",[3832,13791,13782],{"class":3853},[3832,13793,4183],{"class":3849},[3832,13795,4386],{"class":3853},[3832,13797,4183],{"class":3849},[3832,13799,13800],{"class":3853},"status",[3832,13802,5921],{"class":3849},[3832,13804,13057],{"class":5726},[3832,13806,4189],{"class":3849},[3832,13808,13809,13812,13814,13816,13818,13821],{"class":3834,"line":4145},[3832,13810,13811],{"class":3853},"        console",[3832,13813,4183],{"class":3849},[3832,13815,7989],{"class":4117},[3832,13817,4162],{"class":3849},[3832,13819,13820],{"class":3869},"'🔄 Access token застарів, оновлюємо...'",[3832,13822,4168],{"class":3849},[3832,13824,13825],{"class":3834,"line":4171},[3832,13826,11390],{"class":3849},[3832,13828,13829],{"class":3834,"line":4192},[3832,13830,13831],{"class":3838},"        \u002F\u002F Отримуємо refresh token зі стору\n",[3832,13833,13834,13836,13839,13841,13843,13845,13847,13849,13851,13853,13855,13857,13859],{"class":3834,"line":4211},[3832,13835,4148],{"class":3889},[3832,13837,13838],{"class":4042}," refreshToken",[3832,13840,11450],{"class":3849},[3832,13842,9534],{"class":3853},[3832,13844,4183],{"class":3849},[3832,13846,9693],{"class":4117},[3832,13848,11455],{"class":3849},[3832,13850,6999],{"class":3845},[3832,13852,9676],{"class":3893},[3832,13854,5621],{"class":3849},[3832,13856,11465],{"class":3853},[3832,13858,4183],{"class":3849},[3832,13860,13861],{"class":3853},"refreshToken\n",[3832,13863,13864],{"class":3834,"line":4217},[3832,13865,11390],{"class":3849},[3832,13867,13868],{"class":3834,"line":4233},[3832,13869,13870],{"class":3838},"        \u002F\u002F Запитуємо новий access token\n",[3832,13872,13873,13875,13878,13880,13882,13884],{"class":3834,"line":4239},[3832,13874,4148],{"class":3889},[3832,13876,13877],{"class":4042}," refreshResult",[3832,13879,4114],{"class":3849},[3832,13881,4156],{"class":3845},[3832,13883,13542],{"class":4117},[3832,13885,4120],{"class":3849},[3832,13887,13888],{"class":3834,"line":4244},[3832,13889,13890],{"class":3849},"            {\n",[3832,13892,13893,13895,13898],{"class":3834,"line":4249},[3832,13894,6424],{"class":3853},[3832,13896,13897],{"class":3869}," '\u002Fauth\u002Frefresh'",[3832,13899,4072],{"class":3849},[3832,13901,13902,13904,13906],{"class":3834,"line":4255},[3832,13903,6433],{"class":3853},[3832,13905,5125],{"class":3869},[3832,13907,4072],{"class":3849},[3832,13909,13910,13912,13914,13917],{"class":3834,"line":4270},[3832,13911,6442],{"class":3853},[3832,13913,3850],{"class":3849},[3832,13915,13916],{"class":3853},"refreshToken",[3832,13918,5145],{"class":3849},[3832,13920,13921],{"class":3834,"line":4281},[3832,13922,13923],{"class":3849},"            },\n",[3832,13925,13926,13929],{"class":3834,"line":4289},[3832,13927,13928],{"class":3853},"            api",[3832,13930,4072],{"class":3849},[3832,13932,13933,13936],{"class":3834,"line":4298},[3832,13934,13935],{"class":3853},"            extraOptions",[3832,13937,4072],{"class":3849},[3832,13939,13940],{"class":3834,"line":4320},[3832,13941,10048],{"class":3849},[3832,13943,13944],{"class":3834,"line":4326},[3832,13945,3877],{"emptyLinePlaceholder":3876},[3832,13947,13948,13950,13952,13955,13957,13959],{"class":3834,"line":4332},[3832,13949,4174],{"class":3845},[3832,13951,4307],{"class":3849},[3832,13953,13954],{"class":3853},"refreshResult",[3832,13956,4183],{"class":3849},[3832,13958,6565],{"class":3853},[3832,13960,4189],{"class":3849},[3832,13962,13963],{"class":3834,"line":4363},[3832,13964,13965],{"class":3838},"            \u002F\u002F ✅ Успішно оновили токен\n",[3832,13967,13968,13971,13973,13975,13977,13980],{"class":3834,"line":4379},[3832,13969,13970],{"class":3853},"            console",[3832,13972,4183],{"class":3849},[3832,13974,7989],{"class":4117},[3832,13976,4162],{"class":3849},[3832,13978,13979],{"class":3869},"'✅ Токен оновлено успішно'",[3832,13981,4168],{"class":3849},[3832,13983,13984],{"class":3834,"line":4394},[3832,13985,8518],{"class":3849},[3832,13987,13988],{"class":3834,"line":4400},[3832,13989,13990],{"class":3838},"            \u002F\u002F Зберігаємо нові токени у Redux\n",[3832,13992,13993,13995,13997,13999,14001,14003,14005,14007,14009,14011,14014,14016],{"class":3834,"line":4406},[3832,13994,13928],{"class":3853},[3832,13996,4183],{"class":3849},[3832,13998,4809],{"class":4117},[3832,14000,4162],{"class":3849},[3832,14002,12639],{"class":4117},[3832,14004,4162],{"class":3849},[3832,14006,13954],{"class":3853},[3832,14008,4183],{"class":3849},[3832,14010,6565],{"class":3853},[3832,14012,14013],{"class":3845}," as",[3832,14015,11460],{"class":3893},[3832,14017,5506],{"class":3849},[3832,14019,14020],{"class":3834,"line":4437},[3832,14021,8518],{"class":3849},[3832,14023,14024],{"class":3834,"line":4451},[3832,14025,14026],{"class":3838},"            \u002F\u002F Повторюємо початковий запит з новим токеном\n",[3832,14028,14029,14032,14034,14036,14038,14040,14042,14044,14046,14048,14050],{"class":3834,"line":4470},[3832,14030,14031],{"class":3853},"            result",[3832,14033,4114],{"class":3849},[3832,14035,4156],{"class":3845},[3832,14037,13542],{"class":4117},[3832,14039,4162],{"class":3849},[3832,14041,13716],{"class":3853},[3832,14043,3857],{"class":3849},[3832,14045,9534],{"class":3853},[3832,14047,3857],{"class":3849},[3832,14049,13725],{"class":3853},[3832,14051,4168],{"class":3849},[3832,14053,14054,14057,14060],{"class":3834,"line":4475},[3832,14055,14056],{"class":3849},"        } ",[3832,14058,14059],{"class":3845},"else",[3832,14061,3897],{"class":3849},[3832,14063,14064],{"class":3834,"line":4481},[3832,14065,14066],{"class":3838},"            \u002F\u002F ❌ Не вдалося оновити токен — розлогінюємо користувача\n",[3832,14068,14069,14071,14073,14075,14077,14080],{"class":3834,"line":4511},[3832,14070,13970],{"class":3853},[3832,14072,4183],{"class":3849},[3832,14074,7989],{"class":4117},[3832,14076,4162],{"class":3849},[3832,14078,14079],{"class":3869},"'❌ Не вдалося оновити токен, виходимо'",[3832,14081,4168],{"class":3849},[3832,14083,14084,14086,14088,14090,14092,14094],{"class":3834,"line":4524},[3832,14085,13928],{"class":3853},[3832,14087,4183],{"class":3849},[3832,14089,4809],{"class":4117},[3832,14091,4162],{"class":3849},[3832,14093,12644],{"class":4117},[3832,14095,4801],{"class":3849},[3832,14097,14098],{"class":3834,"line":4552},[3832,14099,4214],{"class":3849},[3832,14101,14102],{"class":3834,"line":4557},[3832,14103,4236],{"class":3849},[3832,14105,14106],{"class":3834,"line":4563},[3832,14107,3877],{"emptyLinePlaceholder":3876},[3832,14109,14110,14112],{"class":3834,"line":4569},[3832,14111,4911],{"class":3845},[3832,14113,14114],{"class":3853}," result\n",[3832,14116,14117],{"class":3834,"line":4574},[3832,14118,3945],{"class":3849},[6852,14120,14122],{"id":14121},"використання-у-createapi","Використання у createApi",[3822,14124,14126],{"className":3824,"code":14125,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fservices\u002Fapi.ts\nimport { createApi } from '@reduxjs\u002Ftoolkit\u002Fquery\u002Freact'\nimport { baseQueryWithReauth } from '.\u002FbaseQueryWithReauth'\n\nexport const api = createApi({\n    \u002F\u002F Використовуємо нашу розумну baseQuery замість звичайної\n    baseQuery: baseQueryWithReauth,\n    \n    endpoints: (builder) => ({\n        getProfile: builder.query({\n            query: () => '\u002Fuser\u002Fprofile',\n        }),\n        getTrips: builder.query({\n            query: () => '\u002Ftrips',\n        }),\n    }),\n})\n",[3829,14127,14128,14132,14146,14162,14166,14180,14185,14193,14197,14213,14225,14239,14243,14255,14269,14273,14277],{"__ignoreMap":3827},[3832,14129,14130],{"class":3834,"line":3835},[3832,14131,9193],{"class":3838},[3832,14133,14134,14136,14138,14140,14142,14144],{"class":3834,"line":3842},[3832,14135,3846],{"class":3845},[3832,14137,3850],{"class":3849},[3832,14139,6153],{"class":3853},[3832,14141,3863],{"class":3849},[3832,14143,3866],{"class":3845},[3832,14145,6165],{"class":3869},[3832,14147,14148,14150,14152,14155,14157,14159],{"class":3834,"line":3873},[3832,14149,3846],{"class":3845},[3832,14151,3850],{"class":3849},[3832,14153,14154],{"class":3853},"baseQueryWithReauth",[3832,14156,3863],{"class":3849},[3832,14158,3866],{"class":3845},[3832,14160,14161],{"class":3869}," '.\u002FbaseQueryWithReauth'\n",[3832,14163,14164],{"class":3834,"line":3880},[3832,14165,3877],{"emptyLinePlaceholder":3876},[3832,14167,14168,14170,14172,14174,14176,14178],{"class":3834,"line":3886},[3832,14169,4105],{"class":3845},[3832,14171,4108],{"class":3889},[3832,14173,9277],{"class":4042},[3832,14175,4114],{"class":3849},[3832,14177,6153],{"class":4117},[3832,14179,4267],{"class":3849},[3832,14181,14182],{"class":3834,"line":3900},[3832,14183,14184],{"class":3838},"    \u002F\u002F Використовуємо нашу розумну baseQuery замість звичайної\n",[3832,14186,14187,14189,14191],{"class":3834,"line":3912},[3832,14188,6252],{"class":3853},[3832,14190,13674],{"class":3853},[3832,14192,4072],{"class":3849},[3832,14194,14195],{"class":3834,"line":3922},[3832,14196,4724],{"class":3849},[3832,14198,14199,14201,14203,14205,14207,14209,14211],{"class":3834,"line":3932},[3832,14200,6288],{"class":4117},[3832,14202,4304],{"class":3853},[3832,14204,4307],{"class":3849},[3832,14206,4310],{"class":3853},[3832,14208,4313],{"class":3849},[3832,14210,4140],{"class":3889},[3832,14212,6301],{"class":3849},[3832,14214,14215,14217,14219,14221,14223],{"class":3834,"line":3942},[3832,14216,12904],{"class":3853},[3832,14218,6314],{"class":3853},[3832,14220,4183],{"class":3849},[3832,14222,6319],{"class":4117},[3832,14224,4267],{"class":3849},[3832,14226,14227,14229,14231,14233,14235,14237],{"class":3834,"line":3948},[3832,14228,6337],{"class":4117},[3832,14230,4304],{"class":3853},[3832,14232,4137],{"class":3849},[3832,14234,4140],{"class":3889},[3832,14236,12925],{"class":3869},[3832,14238,4072],{"class":3849},[3832,14240,14241],{"class":3834,"line":3953},[3832,14242,6367],{"class":3849},[3832,14244,14245,14247,14249,14251,14253],{"class":3834,"line":3959},[3832,14246,6311],{"class":3853},[3832,14248,6314],{"class":3853},[3832,14250,4183],{"class":3849},[3832,14252,6319],{"class":4117},[3832,14254,4267],{"class":3849},[3832,14256,14257,14259,14261,14263,14265,14267],{"class":3834,"line":3969},[3832,14258,6337],{"class":4117},[3832,14260,4304],{"class":3853},[3832,14262,4137],{"class":3849},[3832,14264,4140],{"class":3889},[3832,14266,6346],{"class":3869},[3832,14268,4072],{"class":3849},[3832,14270,14271],{"class":3834,"line":3986},[3832,14272,6367],{"class":3849},[3832,14274,14275],{"class":3834,"line":4000},[3832,14276,6475],{"class":3849},[3832,14278,14279],{"class":3834,"line":4020},[3832,14280,4566],{"class":3849},[3801,14282,14283,14286],{},[3770,14284,14285],{},"Тепер все працює автоматично!"," Користувач може не заходити у застосунок тиждень — при першому запиті токен оновиться прозоро.",[8569,14288,14289,14292],{},[3770,14290,14291],{},"Важливе зауваження:"," Refresh token теж може застаріти (наприклад, через 30 днів). У цьому випадку користувачу дійсно доведеться ввести пароль знову. Це нормально і безпечно!",[3809,14294,14296],{"id":14295},"просунута-проблема-паралельні-запити-race-condition","Просунута проблема: Паралельні запити (Race Condition)",[3801,14298,14299],{},"Уявіть ситуацію:",[3822,14301,14303],{"className":4592,"code":14302,"language":4594,"meta":3827,"style":3827},"function DashboardScreen() {\n    \u002F\u002F 3 запити виконуються ОДНОЧАСНО при монтуванні екрана\n    const { data: profile } = useGetProfileQuery()\n    const { data: trips } = useGetTripsQuery()\n    const { data: stats } = useGetStatsQuery()\n    \n    \u002F\u002F Якщо access token застарів, всі 3 запити отримають 401!\n    \u002F\u002F Наївна реалізація спробує оновити токен 3 РАЗИ паралельно\n}\n",[3829,14304,14305,14314,14319,14338,14356,14376,14380,14385,14390],{"__ignoreMap":3827},[3832,14306,14307,14309,14312],{"class":3834,"line":3835},[3832,14308,7416],{"class":3889},[3832,14310,14311],{"class":4117}," DashboardScreen",[3832,14313,4705],{"class":3849},[3832,14315,14316],{"class":3834,"line":3842},[3832,14317,14318],{"class":3838},"    \u002F\u002F 3 запити виконуються ОДНОЧАСНО при монтуванні екрана\n",[3832,14320,14321,14323,14325,14327,14329,14331,14333,14336],{"class":3834,"line":3873},[3832,14322,4710],{"class":3889},[3832,14324,3850],{"class":3849},[3832,14326,6565],{"class":3853},[3832,14328,3906],{"class":3849},[3832,14330,7994],{"class":4042},[3832,14332,4748],{"class":3849},[3832,14334,14335],{"class":4117},"useGetProfileQuery",[3832,14337,4230],{"class":3849},[3832,14339,14340,14342,14344,14346,14348,14350,14352,14354],{"class":3834,"line":3880},[3832,14341,4710],{"class":3889},[3832,14343,3850],{"class":3849},[3832,14345,6565],{"class":3853},[3832,14347,3906],{"class":3849},[3832,14349,4458],{"class":4042},[3832,14351,4748],{"class":3849},[3832,14353,6499],{"class":4117},[3832,14355,4230],{"class":3849},[3832,14357,14358,14360,14362,14364,14366,14369,14371,14374],{"class":3834,"line":3886},[3832,14359,4710],{"class":3889},[3832,14361,3850],{"class":3849},[3832,14363,6565],{"class":3853},[3832,14365,3906],{"class":3849},[3832,14367,14368],{"class":4042},"stats",[3832,14370,4748],{"class":3849},[3832,14372,14373],{"class":4117},"useGetStatsQuery",[3832,14375,4230],{"class":3849},[3832,14377,14378],{"class":3834,"line":3900},[3832,14379,4724],{"class":3849},[3832,14381,14382],{"class":3834,"line":3912},[3832,14383,14384],{"class":3838},"    \u002F\u002F Якщо access token застарів, всі 3 запити отримають 401!\n",[3832,14386,14387],{"class":3834,"line":3922},[3832,14388,14389],{"class":3838},"    \u002F\u002F Наївна реалізація спробує оновити токен 3 РАЗИ паралельно\n",[3832,14391,14392],{"class":3834,"line":3932},[3832,14393,3945],{"class":3849},[3801,14395,14396,14398,14399,14402],{},[3770,14397,5420],{}," 3 паралельні POST-запити на ",[3829,14400,14401],{},"\u002Fauth\u002Frefresh"," можуть:",[3746,14404,14405,14408,14415],{},[3749,14406,14407],{},"Створити навантаження на сервер",[3749,14409,14410,14411,14414],{},"Викликати ",[3817,14412,14413],{},"race condition"," (перший токен перезаписується другим)",[3749,14416,14417],{},"Призвести до інвалідації refresh token деякими backend системами",[3809,14419,14421],{"id":14420},"рішення-mutex-взаємне-блокування","Рішення: Mutex (взаємне блокування)",[3801,14423,14424,4307,14427,14430],{},[3770,14425,14426],{},"Mutex",[3817,14428,14429],{},"Mutual Exclusion",") — патерн, який гарантує, що тільки один запит може виконувати refresh у конкретний момент часу.",[3801,14432,14433],{},"Спочатку встановимо бібліотеку:",[3822,14435,14437],{"className":9112,"code":14436,"language":9114,"meta":3827,"style":3827},"npm install async-mutex\n",[3829,14438,14439],{"__ignoreMap":3827},[3832,14440,14441,14443,14445],{"class":3834,"line":3835},[3832,14442,9109],{"class":4117},[3832,14444,9123],{"class":3869},[3832,14446,14447],{"class":3869}," async-mutex\n",[3801,14449,14450],{},"Тепер оновимо нашу логіку:",[3822,14452,14454],{"className":3824,"code":14453,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fservices\u002FbaseQueryWithReauth.ts\nimport { fetchBaseQuery } from '@reduxjs\u002Ftoolkit\u002Fquery'\nimport type { BaseQueryFn, FetchArgs, FetchBaseQueryError } from '@reduxjs\u002Ftoolkit\u002Fquery'\nimport { Mutex } from 'async-mutex'\nimport { setCredentials, logout } from '@\u002Fstore\u002FauthSlice'\nimport type { RootState } from '@\u002Fstore'\n\n\u002F\u002F Створюємо єдиний mutex для всього застосунку\nconst mutex = new Mutex()\n\nconst baseQuery = fetchBaseQuery({\n    baseUrl: 'https:\u002F\u002Fapi.example.com',\n    prepareHeaders: (headers, { getState }) => {\n        const token = (getState() as RootState).auth.token\n        if (token) {\n            headers.set('Authorization', `Bearer ${token}`)\n        }\n        return headers\n    },\n})\n\nexport const baseQueryWithReauth: BaseQueryFn\u003C\n    string | FetchArgs,\n    unknown,\n    FetchBaseQueryError\n> = async (args, api, extraOptions) => {\n    \u002F\u002F 🔒 Чекаємо, поки mutex буде вільний\n    \u002F\u002F Якщо хтось вже оновлює токен — почекаємо\n    await mutex.waitForUnlock()\n    \n    let result = await baseQuery(args, api, extraOptions)\n\n    if (result.error && result.error.status === 401) {\n        \u002F\u002F Перевіряємо: може інший запит вже захопив mutex?\n        if (!mutex.isLocked()) {\n            \u002F\u002F 🔒 Захоплюємо mutex — тепер тільки ми можемо оновлювати токен\n            const release = await mutex.acquire()\n            \n            try {\n                console.log('🔄 Оновлюю токен (mutex захоплено)')\n                \n                const refreshToken = (api.getState() as RootState).auth.refreshToken\n                \n                const refreshResult = await baseQuery(\n                    {\n                        url: '\u002Fauth\u002Frefresh',\n                        method: 'POST',\n                        body: { refreshToken },\n                    },\n                    api,\n                    extraOptions,\n                )\n\n                if (refreshResult.data) {\n                    console.log('✅ Токен оновлено, звільняю mutex')\n                    api.dispatch(setCredentials(refreshResult.data as any))\n                    \n                    \u002F\u002F Повторюємо початковий запит\n                    result = await baseQuery(args, api, extraOptions)\n                } else {\n                    console.log('❌ Refresh провалився, виходимо')\n                    api.dispatch(logout())\n                }\n            } finally {\n                \u002F\u002F 🔓 ОБОВ'ЯЗКОВО звільняємо mutex\n                release()\n            }\n        } else {\n            \u002F\u002F Інший запит вже оновлює токен\n            \u002F\u002F Просто чекаємо його завершення та повторюємо запит\n            console.log('⏳ Чекаю завершення refresh від іншого запиту...')\n            await mutex.waitForUnlock()\n            \n            \u002F\u002F Токен вже оновлено — повторюємо запит\n            result = await baseQuery(args, api, extraOptions)\n        }\n    }\n\n    return result\n}\n",[3829,14455,14456,14460,14474,14498,14513,14531,14547,14551,14556,14572,14576,14588,14596,14616,14640,14650,14676,14680,14686,14690,14694,14698,14712,14722,14728,14732,14756,14761,14766,14779,14783,14809,14813,14843,14848,14865,14870,14890,14894,14901,14917,14922,14951,14955,14969,14974,14983,14992,15003,15008,15015,15022,15027,15031,15046,15062,15088,15093,15098,15123,15132,15147,15161,15166,15176,15181,15188,15192,15200,15205,15210,15225,15238,15242,15247,15271,15275,15279,15283,15289],{"__ignoreMap":3827},[3832,14457,14458],{"class":3834,"line":3835},[3832,14459,13450],{"class":3838},[3832,14461,14462,14464,14466,14468,14470,14472],{"class":3834,"line":3842},[3832,14463,3846],{"class":3845},[3832,14465,3850],{"class":3849},[3832,14467,6158],{"class":3853},[3832,14469,3863],{"class":3849},[3832,14471,3866],{"class":3845},[3832,14473,9525],{"class":3869},[3832,14475,14476,14478,14480,14482,14484,14486,14488,14490,14492,14494,14496],{"class":3834,"line":3873},[3832,14477,3846],{"class":3845},[3832,14479,9673],{"class":3845},[3832,14481,3850],{"class":3849},[3832,14483,13475],{"class":3853},[3832,14485,3857],{"class":3849},[3832,14487,13480],{"class":3853},[3832,14489,3857],{"class":3849},[3832,14491,13485],{"class":3853},[3832,14493,3863],{"class":3849},[3832,14495,3866],{"class":3845},[3832,14497,9525],{"class":3869},[3832,14499,14500,14502,14504,14506,14508,14510],{"class":3834,"line":3880},[3832,14501,3846],{"class":3845},[3832,14503,3850],{"class":3849},[3832,14505,14426],{"class":3853},[3832,14507,3863],{"class":3849},[3832,14509,3866],{"class":3845},[3832,14511,14512],{"class":3869}," 'async-mutex'\n",[3832,14514,14515,14517,14519,14521,14523,14525,14527,14529],{"class":3834,"line":3886},[3832,14516,3846],{"class":3845},[3832,14518,3850],{"class":3849},[3832,14520,12639],{"class":3853},[3832,14522,3857],{"class":3849},[3832,14524,12644],{"class":3853},[3832,14526,3863],{"class":3849},[3832,14528,3866],{"class":3845},[3832,14530,13510],{"class":3869},[3832,14532,14533,14535,14537,14539,14541,14543,14545],{"class":3834,"line":3900},[3832,14534,3846],{"class":3845},[3832,14536,9673],{"class":3845},[3832,14538,3850],{"class":3849},[3832,14540,12711],{"class":3853},[3832,14542,3863],{"class":3849},[3832,14544,3866],{"class":3845},[3832,14546,12718],{"class":3869},[3832,14548,14549],{"class":3834,"line":3912},[3832,14550,3877],{"emptyLinePlaceholder":3876},[3832,14552,14553],{"class":3834,"line":3922},[3832,14554,14555],{"class":3838},"\u002F\u002F Створюємо єдиний mutex для всього застосунку\n",[3832,14557,14558,14560,14563,14565,14567,14570],{"class":3834,"line":3932},[3832,14559,4039],{"class":3889},[3832,14561,14562],{"class":4042}," mutex",[3832,14564,4114],{"class":3849},[3832,14566,7494],{"class":3889},[3832,14568,14569],{"class":4117}," Mutex",[3832,14571,4230],{"class":3849},[3832,14573,14574],{"class":3834,"line":3942},[3832,14575,3877],{"emptyLinePlaceholder":3876},[3832,14577,14578,14580,14582,14584,14586],{"class":3834,"line":3948},[3832,14579,4039],{"class":3889},[3832,14581,13542],{"class":4042},[3832,14583,4114],{"class":3849},[3832,14585,6158],{"class":4117},[3832,14587,4267],{"class":3849},[3832,14589,14590,14592,14594],{"class":3834,"line":3953},[3832,14591,13553],{"class":3853},[3832,14593,12751],{"class":3869},[3832,14595,4072],{"class":3849},[3832,14597,14598,14600,14602,14604,14606,14608,14610,14612,14614],{"class":3834,"line":3959},[3832,14599,13562],{"class":4117},[3832,14601,4304],{"class":3853},[3832,14603,4307],{"class":3849},[3832,14605,8912],{"class":3853},[3832,14607,4611],{"class":3849},[3832,14609,9693],{"class":3853},[3832,14611,4981],{"class":3849},[3832,14613,4140],{"class":3889},[3832,14615,3897],{"class":3849},[3832,14617,14618,14620,14622,14624,14626,14628,14630,14632,14634,14636,14638],{"class":3834,"line":3969},[3832,14619,4148],{"class":3889},[3832,14621,11447],{"class":4042},[3832,14623,11450],{"class":3849},[3832,14625,9693],{"class":4117},[3832,14627,11455],{"class":3849},[3832,14629,6999],{"class":3845},[3832,14631,9676],{"class":3893},[3832,14633,5621],{"class":3849},[3832,14635,11465],{"class":3853},[3832,14637,4183],{"class":3849},[3832,14639,11470],{"class":3853},[3832,14641,14642,14644,14646,14648],{"class":3834,"line":3986},[3832,14643,4174],{"class":3845},[3832,14645,4307],{"class":3849},[3832,14647,11484],{"class":3853},[3832,14649,4189],{"class":3849},[3832,14651,14652,14654,14656,14658,14660,14662,14664,14666,14668,14670,14672,14674],{"class":3834,"line":4000},[3832,14653,8923],{"class":3853},[3832,14655,4183],{"class":3849},[3832,14657,8928],{"class":4117},[3832,14659,4162],{"class":3849},[3832,14661,11500],{"class":3869},[3832,14663,3857],{"class":3849},[3832,14665,11505],{"class":3869},[3832,14667,11249],{"class":3889},[3832,14669,11484],{"class":3853},[3832,14671,4890],{"class":3889},[3832,14673,11514],{"class":3869},[3832,14675,4168],{"class":3849},[3832,14677,14678],{"class":3834,"line":4020},[3832,14679,4214],{"class":3849},[3832,14681,14682,14684],{"class":3834,"line":4025},[3832,14683,4220],{"class":3845},[3832,14685,8947],{"class":3853},[3832,14687,14688],{"class":3834,"line":4030},[3832,14689,4560],{"class":3849},[3832,14691,14692],{"class":3834,"line":4036},[3832,14693,4566],{"class":3849},[3832,14695,14696],{"class":3834,"line":4054},[3832,14697,3877],{"emptyLinePlaceholder":3876},[3832,14699,14700,14702,14704,14706,14708,14710],{"class":3834,"line":4063},[3832,14701,4105],{"class":3845},[3832,14703,4108],{"class":3889},[3832,14705,13674],{"class":4042},[3832,14707,3906],{"class":3849},[3832,14709,13475],{"class":3893},[3832,14711,13681],{"class":3849},[3832,14713,14714,14716,14718,14720],{"class":3834,"line":4075},[3832,14715,13686],{"class":3893},[3832,14717,4011],{"class":3849},[3832,14719,13480],{"class":3893},[3832,14721,4072],{"class":3849},[3832,14723,14724,14726],{"class":3834,"line":4086},[3832,14725,13697],{"class":3893},[3832,14727,4072],{"class":3849},[3832,14729,14730],{"class":3834,"line":4091},[3832,14731,13704],{"class":3893},[3832,14733,14734,14736,14738,14740,14742,14744,14746,14748,14750,14752,14754],{"class":3834,"line":4096},[3832,14735,13709],{"class":3849},[3832,14737,5477],{"class":3889},[3832,14739,4307],{"class":3849},[3832,14741,13716],{"class":3853},[3832,14743,3857],{"class":3849},[3832,14745,9534],{"class":3853},[3832,14747,3857],{"class":3849},[3832,14749,13725],{"class":3853},[3832,14751,4313],{"class":3849},[3832,14753,4140],{"class":3889},[3832,14755,3897],{"class":3849},[3832,14757,14758],{"class":3834,"line":4102},[3832,14759,14760],{"class":3838},"    \u002F\u002F 🔒 Чекаємо, поки mutex буде вільний\n",[3832,14762,14763],{"class":3834,"line":4123},[3832,14764,14765],{"class":3838},"    \u002F\u002F Якщо хтось вже оновлює токен — почекаємо\n",[3832,14767,14768,14770,14772,14774,14777],{"class":3834,"line":4131},[3832,14769,5493],{"class":3845},[3832,14771,14562],{"class":3853},[3832,14773,4183],{"class":3849},[3832,14775,14776],{"class":4117},"waitForUnlock",[3832,14778,4230],{"class":3849},[3832,14780,14781],{"class":3834,"line":4145},[3832,14782,4724],{"class":3849},[3832,14784,14785,14787,14789,14791,14793,14795,14797,14799,14801,14803,14805,14807],{"class":3834,"line":4171},[3832,14786,13741],{"class":3889},[3832,14788,13744],{"class":3853},[3832,14790,4114],{"class":3849},[3832,14792,4156],{"class":3845},[3832,14794,13542],{"class":4117},[3832,14796,4162],{"class":3849},[3832,14798,13716],{"class":3853},[3832,14800,3857],{"class":3849},[3832,14802,9534],{"class":3853},[3832,14804,3857],{"class":3849},[3832,14806,13725],{"class":3853},[3832,14808,4168],{"class":3849},[3832,14810,14811],{"class":3834,"line":4192},[3832,14812,3877],{"emptyLinePlaceholder":3876},[3832,14814,14815,14817,14819,14821,14823,14825,14827,14829,14831,14833,14835,14837,14839,14841],{"class":3834,"line":4211},[3832,14816,4821],{"class":3845},[3832,14818,4307],{"class":3849},[3832,14820,13782],{"class":3853},[3832,14822,4183],{"class":3849},[3832,14824,4386],{"class":3853},[3832,14826,13789],{"class":3849},[3832,14828,13782],{"class":3853},[3832,14830,4183],{"class":3849},[3832,14832,4386],{"class":3853},[3832,14834,4183],{"class":3849},[3832,14836,13800],{"class":3853},[3832,14838,5921],{"class":3849},[3832,14840,13057],{"class":5726},[3832,14842,4189],{"class":3849},[3832,14844,14845],{"class":3834,"line":4217},[3832,14846,14847],{"class":3838},"        \u002F\u002F Перевіряємо: може інший запит вже захопив mutex?\n",[3832,14849,14850,14852,14854,14857,14859,14862],{"class":3834,"line":4233},[3832,14851,4174],{"class":3845},[3832,14853,4177],{"class":3849},[3832,14855,14856],{"class":3853},"mutex",[3832,14858,4183],{"class":3849},[3832,14860,14861],{"class":4117},"isLocked",[3832,14863,14864],{"class":3849},"()) {\n",[3832,14866,14867],{"class":3834,"line":4239},[3832,14868,14869],{"class":3838},"            \u002F\u002F 🔒 Захоплюємо mutex — тепер тільки ми можемо оновлювати токен\n",[3832,14871,14872,14874,14877,14879,14881,14883,14885,14888],{"class":3834,"line":4244},[3832,14873,11444],{"class":3889},[3832,14875,14876],{"class":4042}," release",[3832,14878,4114],{"class":3849},[3832,14880,4156],{"class":3845},[3832,14882,14562],{"class":3853},[3832,14884,4183],{"class":3849},[3832,14886,14887],{"class":4117},"acquire",[3832,14889,4230],{"class":3849},[3832,14891,14892],{"class":3834,"line":4249},[3832,14893,8518],{"class":3849},[3832,14895,14896,14899],{"class":3834,"line":4255},[3832,14897,14898],{"class":3845},"            try",[3832,14900,3897],{"class":3849},[3832,14902,14903,14906,14908,14910,14912,14915],{"class":3834,"line":4270},[3832,14904,14905],{"class":3853},"                console",[3832,14907,4183],{"class":3849},[3832,14909,7989],{"class":4117},[3832,14911,4162],{"class":3849},[3832,14913,14914],{"class":3869},"'🔄 Оновлюю токен (mutex захоплено)'",[3832,14916,4168],{"class":3849},[3832,14918,14919],{"class":3834,"line":4281},[3832,14920,14921],{"class":3849},"                \n",[3832,14923,14924,14927,14929,14931,14933,14935,14937,14939,14941,14943,14945,14947,14949],{"class":3834,"line":4289},[3832,14925,14926],{"class":3889},"                const",[3832,14928,13838],{"class":4042},[3832,14930,11450],{"class":3849},[3832,14932,9534],{"class":3853},[3832,14934,4183],{"class":3849},[3832,14936,9693],{"class":4117},[3832,14938,11455],{"class":3849},[3832,14940,6999],{"class":3845},[3832,14942,9676],{"class":3893},[3832,14944,5621],{"class":3849},[3832,14946,11465],{"class":3853},[3832,14948,4183],{"class":3849},[3832,14950,13861],{"class":3853},[3832,14952,14953],{"class":3834,"line":4298},[3832,14954,14921],{"class":3849},[3832,14956,14957,14959,14961,14963,14965,14967],{"class":3834,"line":4320},[3832,14958,14926],{"class":3889},[3832,14960,13877],{"class":4042},[3832,14962,4114],{"class":3849},[3832,14964,4156],{"class":3845},[3832,14966,13542],{"class":4117},[3832,14968,4120],{"class":3849},[3832,14970,14971],{"class":3834,"line":4326},[3832,14972,14973],{"class":3849},"                    {\n",[3832,14975,14976,14979,14981],{"class":3834,"line":4332},[3832,14977,14978],{"class":3853},"                        url:",[3832,14980,13897],{"class":3869},[3832,14982,4072],{"class":3849},[3832,14984,14985,14988,14990],{"class":3834,"line":4363},[3832,14986,14987],{"class":3853},"                        method:",[3832,14989,5125],{"class":3869},[3832,14991,4072],{"class":3849},[3832,14993,14994,14997,14999,15001],{"class":3834,"line":4379},[3832,14995,14996],{"class":3853},"                        body:",[3832,14998,3850],{"class":3849},[3832,15000,13916],{"class":3853},[3832,15002,5145],{"class":3849},[3832,15004,15005],{"class":3834,"line":4394},[3832,15006,15007],{"class":3849},"                    },\n",[3832,15009,15010,15013],{"class":3834,"line":4400},[3832,15011,15012],{"class":3853},"                    api",[3832,15014,4072],{"class":3849},[3832,15016,15017,15020],{"class":3834,"line":4406},[3832,15018,15019],{"class":3853},"                    extraOptions",[3832,15021,4072],{"class":3849},[3832,15023,15024],{"class":3834,"line":4437},[3832,15025,15026],{"class":3849},"                )\n",[3832,15028,15029],{"class":3834,"line":4451},[3832,15030,3877],{"emptyLinePlaceholder":3876},[3832,15032,15033,15036,15038,15040,15042,15044],{"class":3834,"line":4470},[3832,15034,15035],{"class":3845},"                if",[3832,15037,4307],{"class":3849},[3832,15039,13954],{"class":3853},[3832,15041,4183],{"class":3849},[3832,15043,6565],{"class":3853},[3832,15045,4189],{"class":3849},[3832,15047,15048,15051,15053,15055,15057,15060],{"class":3834,"line":4475},[3832,15049,15050],{"class":3853},"                    console",[3832,15052,4183],{"class":3849},[3832,15054,7989],{"class":4117},[3832,15056,4162],{"class":3849},[3832,15058,15059],{"class":3869},"'✅ Токен оновлено, звільняю mutex'",[3832,15061,4168],{"class":3849},[3832,15063,15064,15066,15068,15070,15072,15074,15076,15078,15080,15082,15084,15086],{"class":3834,"line":4481},[3832,15065,15012],{"class":3853},[3832,15067,4183],{"class":3849},[3832,15069,4809],{"class":4117},[3832,15071,4162],{"class":3849},[3832,15073,12639],{"class":4117},[3832,15075,4162],{"class":3849},[3832,15077,13954],{"class":3853},[3832,15079,4183],{"class":3849},[3832,15081,6565],{"class":3853},[3832,15083,14013],{"class":3845},[3832,15085,11460],{"class":3893},[3832,15087,5506],{"class":3849},[3832,15089,15090],{"class":3834,"line":4511},[3832,15091,15092],{"class":3849},"                    \n",[3832,15094,15095],{"class":3834,"line":4524},[3832,15096,15097],{"class":3838},"                    \u002F\u002F Повторюємо початковий запит\n",[3832,15099,15100,15103,15105,15107,15109,15111,15113,15115,15117,15119,15121],{"class":3834,"line":4552},[3832,15101,15102],{"class":3853},"                    result",[3832,15104,4114],{"class":3849},[3832,15106,4156],{"class":3845},[3832,15108,13542],{"class":4117},[3832,15110,4162],{"class":3849},[3832,15112,13716],{"class":3853},[3832,15114,3857],{"class":3849},[3832,15116,9534],{"class":3853},[3832,15118,3857],{"class":3849},[3832,15120,13725],{"class":3853},[3832,15122,4168],{"class":3849},[3832,15124,15125,15128,15130],{"class":3834,"line":4557},[3832,15126,15127],{"class":3849},"                } ",[3832,15129,14059],{"class":3845},[3832,15131,3897],{"class":3849},[3832,15133,15134,15136,15138,15140,15142,15145],{"class":3834,"line":4563},[3832,15135,15050],{"class":3853},[3832,15137,4183],{"class":3849},[3832,15139,7989],{"class":4117},[3832,15141,4162],{"class":3849},[3832,15143,15144],{"class":3869},"'❌ Refresh провалився, виходимо'",[3832,15146,4168],{"class":3849},[3832,15148,15149,15151,15153,15155,15157,15159],{"class":3834,"line":4569},[3832,15150,15012],{"class":3853},[3832,15152,4183],{"class":3849},[3832,15154,4809],{"class":4117},[3832,15156,4162],{"class":3849},[3832,15158,12644],{"class":4117},[3832,15160,4801],{"class":3849},[3832,15162,15163],{"class":3834,"line":4574},[3832,15164,15165],{"class":3849},"                }\n",[3832,15167,15168,15171,15174],{"class":3834,"line":10534},[3832,15169,15170],{"class":3849},"            } ",[3832,15172,15173],{"class":3845},"finally",[3832,15175,3897],{"class":3849},[3832,15177,15178],{"class":3834,"line":10545},[3832,15179,15180],{"class":3838},"                \u002F\u002F 🔓 ОБОВ'ЯЗКОВО звільняємо mutex\n",[3832,15182,15183,15186],{"class":3834,"line":10554},[3832,15184,15185],{"class":4117},"                release",[3832,15187,4230],{"class":3849},[3832,15189,15190],{"class":3834,"line":10564},[3832,15191,11521],{"class":3849},[3832,15193,15194,15196,15198],{"class":3834,"line":10573},[3832,15195,14056],{"class":3849},[3832,15197,14059],{"class":3845},[3832,15199,3897],{"class":3849},[3832,15201,15202],{"class":3834,"line":10583},[3832,15203,15204],{"class":3838},"            \u002F\u002F Інший запит вже оновлює токен\n",[3832,15206,15207],{"class":3834,"line":10593},[3832,15208,15209],{"class":3838},"            \u002F\u002F Просто чекаємо його завершення та повторюємо запит\n",[3832,15211,15212,15214,15216,15218,15220,15223],{"class":3834,"line":10617},[3832,15213,13970],{"class":3853},[3832,15215,4183],{"class":3849},[3832,15217,7989],{"class":4117},[3832,15219,4162],{"class":3849},[3832,15221,15222],{"class":3869},"'⏳ Чекаю завершення refresh від іншого запиту...'",[3832,15224,4168],{"class":3849},[3832,15226,15227,15230,15232,15234,15236],{"class":3834,"line":10628},[3832,15228,15229],{"class":3845},"            await",[3832,15231,14562],{"class":3853},[3832,15233,4183],{"class":3849},[3832,15235,14776],{"class":4117},[3832,15237,4230],{"class":3849},[3832,15239,15240],{"class":3834,"line":10639},[3832,15241,8518],{"class":3849},[3832,15243,15244],{"class":3834,"line":10650},[3832,15245,15246],{"class":3838},"            \u002F\u002F Токен вже оновлено — повторюємо запит\n",[3832,15248,15249,15251,15253,15255,15257,15259,15261,15263,15265,15267,15269],{"class":3834,"line":10655},[3832,15250,14031],{"class":3853},[3832,15252,4114],{"class":3849},[3832,15254,4156],{"class":3845},[3832,15256,13542],{"class":4117},[3832,15258,4162],{"class":3849},[3832,15260,13716],{"class":3853},[3832,15262,3857],{"class":3849},[3832,15264,9534],{"class":3853},[3832,15266,3857],{"class":3849},[3832,15268,13725],{"class":3853},[3832,15270,4168],{"class":3849},[3832,15272,15273],{"class":3834,"line":10663},[3832,15274,4214],{"class":3849},[3832,15276,15277],{"class":3834,"line":10672},[3832,15278,4236],{"class":3849},[3832,15280,15281],{"class":3834,"line":10683},[3832,15282,3877],{"emptyLinePlaceholder":3876},[3832,15284,15285,15287],{"class":3834,"line":10693},[3832,15286,4911],{"class":3845},[3832,15288,14114],{"class":3853},[3832,15290,15291],{"class":3834,"line":10704},[3832,15292,3945],{"class":3849},[3801,15294,15295],{},[3770,15296,12046],{},[8090,15298,15300],{"alt":15299},"Mutex захист від паралельних refresh",[3822,15301,15303],{"className":8095,"code":15302,"language":8097,"meta":3827,"style":3827},"@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\nskinparam defaultFontName \"Helvetica\"\n\nparticipant \"Request 1\\n(getProfile)\" as R1 #DBEAFE\nparticipant \"Request 2\\n(getTrips)\" as R2 #DCFCE7\nparticipant \"Request 3\\n(getStats)\" as R3 #FED7AA\nparticipant \"Mutex\" as M #FEF3C7\nparticipant \"API Server\" as API #FECACA\n\n== Всі запити отримують 401 одночасно ==\nR1 -> M : Перевіряю mutex.isLocked()\nM --> R1 : false (вільний)\nR1 -> M : mutex.acquire() 🔒\nM --> R1 : Захоплено!\n\nR2 -> M : Перевіряю mutex.isLocked()\nM --> R2 : true (зайнятий)\nR2 -> R2 : Чекаю mutex.waitForUnlock()\n\nR3 -> M : Перевіряю mutex.isLocked()\nM --> R3 : true (зайнятий)\nR3 -> R3 : Чекаю mutex.waitForUnlock()\n\n== Request 1 оновлює токен ==\nR1 -> API : POST \u002Fauth\u002Frefresh\nAPI --> R1 : { newAccessToken }\nR1 -> R1 : Зберігаю у Redux\nR1 -> M : release() 🔓\n\n== Інші запити продовжують роботу ==\nM --> R2 : Mutex звільнено!\nM --> R3 : Mutex звільнено!\n\nR2 -> API : GET \u002Ftrips (з НОВИМ токеном)\nR3 -> API : GET \u002Fstats (з НОВИМ токеном)\nAPI --> R2 : 200 OK\nAPI --> R3 : 200 OK\n\n@enduml\n",[3829,15304,15305,15309,15313,15317,15321,15325,15330,15335,15340,15345,15350,15354,15359,15364,15369,15374,15379,15383,15388,15393,15398,15402,15407,15412,15417,15421,15426,15431,15436,15441,15446,15450,15455,15460,15465,15469,15474,15479,15484,15489,15493],{"__ignoreMap":3827},[3832,15306,15307],{"class":3834,"line":3835},[3832,15308,8104],{},[3832,15310,15311],{"class":3834,"line":3842},[3832,15312,8109],{},[3832,15314,15315],{"class":3834,"line":3873},[3832,15316,8114],{},[3832,15318,15319],{"class":3834,"line":3880},[3832,15320,8119],{},[3832,15322,15323],{"class":3834,"line":3886},[3832,15324,3877],{"emptyLinePlaceholder":3876},[3832,15326,15327],{"class":3834,"line":3900},[3832,15328,15329],{},"participant \"Request 1\\n(getProfile)\" as R1 #DBEAFE\n",[3832,15331,15332],{"class":3834,"line":3912},[3832,15333,15334],{},"participant \"Request 2\\n(getTrips)\" as R2 #DCFCE7\n",[3832,15336,15337],{"class":3834,"line":3922},[3832,15338,15339],{},"participant \"Request 3\\n(getStats)\" as R3 #FED7AA\n",[3832,15341,15342],{"class":3834,"line":3932},[3832,15343,15344],{},"participant \"Mutex\" as M #FEF3C7\n",[3832,15346,15347],{"class":3834,"line":3942},[3832,15348,15349],{},"participant \"API Server\" as API #FECACA\n",[3832,15351,15352],{"class":3834,"line":3948},[3832,15353,3877],{"emptyLinePlaceholder":3876},[3832,15355,15356],{"class":3834,"line":3953},[3832,15357,15358],{},"== Всі запити отримують 401 одночасно ==\n",[3832,15360,15361],{"class":3834,"line":3959},[3832,15362,15363],{},"R1 -> M : Перевіряю mutex.isLocked()\n",[3832,15365,15366],{"class":3834,"line":3969},[3832,15367,15368],{},"M --> R1 : false (вільний)\n",[3832,15370,15371],{"class":3834,"line":3986},[3832,15372,15373],{},"R1 -> M : mutex.acquire() 🔒\n",[3832,15375,15376],{"class":3834,"line":4000},[3832,15377,15378],{},"M --> R1 : Захоплено!\n",[3832,15380,15381],{"class":3834,"line":4020},[3832,15382,3877],{"emptyLinePlaceholder":3876},[3832,15384,15385],{"class":3834,"line":4025},[3832,15386,15387],{},"R2 -> M : Перевіряю mutex.isLocked()\n",[3832,15389,15390],{"class":3834,"line":4030},[3832,15391,15392],{},"M --> R2 : true (зайнятий)\n",[3832,15394,15395],{"class":3834,"line":4036},[3832,15396,15397],{},"R2 -> R2 : Чекаю mutex.waitForUnlock()\n",[3832,15399,15400],{"class":3834,"line":4054},[3832,15401,3877],{"emptyLinePlaceholder":3876},[3832,15403,15404],{"class":3834,"line":4063},[3832,15405,15406],{},"R3 -> M : Перевіряю mutex.isLocked()\n",[3832,15408,15409],{"class":3834,"line":4075},[3832,15410,15411],{},"M --> R3 : true (зайнятий)\n",[3832,15413,15414],{"class":3834,"line":4086},[3832,15415,15416],{},"R3 -> R3 : Чекаю mutex.waitForUnlock()\n",[3832,15418,15419],{"class":3834,"line":4091},[3832,15420,3877],{"emptyLinePlaceholder":3876},[3832,15422,15423],{"class":3834,"line":4096},[3832,15424,15425],{},"== Request 1 оновлює токен ==\n",[3832,15427,15428],{"class":3834,"line":4102},[3832,15429,15430],{},"R1 -> API : POST \u002Fauth\u002Frefresh\n",[3832,15432,15433],{"class":3834,"line":4123},[3832,15434,15435],{},"API --> R1 : { newAccessToken }\n",[3832,15437,15438],{"class":3834,"line":4131},[3832,15439,15440],{},"R1 -> R1 : Зберігаю у Redux\n",[3832,15442,15443],{"class":3834,"line":4145},[3832,15444,15445],{},"R1 -> M : release() 🔓\n",[3832,15447,15448],{"class":3834,"line":4171},[3832,15449,3877],{"emptyLinePlaceholder":3876},[3832,15451,15452],{"class":3834,"line":4192},[3832,15453,15454],{},"== Інші запити продовжують роботу ==\n",[3832,15456,15457],{"class":3834,"line":4211},[3832,15458,15459],{},"M --> R2 : Mutex звільнено!\n",[3832,15461,15462],{"class":3834,"line":4217},[3832,15463,15464],{},"M --> R3 : Mutex звільнено!\n",[3832,15466,15467],{"class":3834,"line":4233},[3832,15468,3877],{"emptyLinePlaceholder":3876},[3832,15470,15471],{"class":3834,"line":4239},[3832,15472,15473],{},"R2 -> API : GET \u002Ftrips (з НОВИМ токеном)\n",[3832,15475,15476],{"class":3834,"line":4244},[3832,15477,15478],{},"R3 -> API : GET \u002Fstats (з НОВИМ токеном)\n",[3832,15480,15481],{"class":3834,"line":4249},[3832,15482,15483],{},"API --> R2 : 200 OK\n",[3832,15485,15486],{"class":3834,"line":4255},[3832,15487,15488],{},"API --> R3 : 200 OK\n",[3832,15490,15491],{"class":3834,"line":4270},[3832,15492,3877],{"emptyLinePlaceholder":3876},[3832,15494,15495],{"class":3834,"line":4281},[3832,15496,8288],{},[6795,15498,15499,15502,15503,15506],{},[3770,15500,15501],{},"Підсумок:"," Mutex гарантує, що навіть якщо 100 запитів одночасно отримають 401, тільки ",[3770,15504,15505],{},"перший"," виконає refresh. Всі інші почекають його завершення та автоматично використають оновлений токен.",[3793,15508],{},[3796,15510,15512],{"id":15511},"читання-даних-query-endpoints","Читання даних: Query Endpoints",[3801,15514,15515,15516,15519],{},"Тепер, коли ми розуміємо базову конфігурацію та авторизацію, давайте навчимося описувати ",[3770,15517,15518],{},"Query Endpoints"," — операції читання даних з сервера. Почнемо з найпростішого прикладу та поступово додаватимемо складність.",[3809,15521,15523],{"id":15522},"рівень-1-найпростіший-get-запит-без-параметрів","Рівень 1: Найпростіший GET-запит без параметрів",[3801,15525,15526],{},"Це базовий випадок — просто отримати список даних з сервера:",[3822,15528,15530],{"className":3824,"code":15529,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fservices\u002Fapi.ts\nimport { createApi, fetchBaseQuery } from '@reduxjs\u002Ftoolkit\u002Fquery\u002Freact'\n\ninterface Post {\n    id: number\n    title: string\n    body: string\n}\n\nexport const api = createApi({\n    baseQuery: fetchBaseQuery({ baseUrl: 'https:\u002F\u002Fjsonplaceholder.typicode.com' }),\n    endpoints: (builder) => ({\n        \u002F\u002F Query без аргументів — тип \u003CТипВідповіді, void>\n        getPosts: builder.query\u003CPost[], void>({\n            query: () => '\u002Fposts',\n        }),\n    }),\n})\n\nexport const { useGetPostsQuery } = api\n",[3829,15531,15532,15536,15554,15558,15566,15574,15582,15590,15594,15598,15612,15626,15642,15647,15667,15681,15685,15689,15693,15697],{"__ignoreMap":3827},[3832,15533,15534],{"class":3834,"line":3835},[3832,15535,9193],{"class":3838},[3832,15537,15538,15540,15542,15544,15546,15548,15550,15552],{"class":3834,"line":3842},[3832,15539,3846],{"class":3845},[3832,15541,3850],{"class":3849},[3832,15543,6153],{"class":3853},[3832,15545,3857],{"class":3849},[3832,15547,6158],{"class":3853},[3832,15549,3863],{"class":3849},[3832,15551,3866],{"class":3845},[3832,15553,6165],{"class":3869},[3832,15555,15556],{"class":3834,"line":3873},[3832,15557,3877],{"emptyLinePlaceholder":3876},[3832,15559,15560,15562,15564],{"class":3834,"line":3880},[3832,15561,3890],{"class":3889},[3832,15563,9227],{"class":3893},[3832,15565,3897],{"class":3849},[3832,15567,15568,15570,15572],{"class":3834,"line":3886},[3832,15569,3903],{"class":3853},[3832,15571,3906],{"class":3849},[3832,15573,9238],{"class":3893},[3832,15575,15576,15578,15580],{"class":3834,"line":3900},[3832,15577,3915],{"class":3853},[3832,15579,3906],{"class":3849},[3832,15581,3909],{"class":3893},[3832,15583,15584,15586,15588],{"class":3834,"line":3912},[3832,15585,9251],{"class":3853},[3832,15587,3906],{"class":3849},[3832,15589,3909],{"class":3893},[3832,15591,15592],{"class":3834,"line":3922},[3832,15593,3945],{"class":3849},[3832,15595,15596],{"class":3834,"line":3932},[3832,15597,3877],{"emptyLinePlaceholder":3876},[3832,15599,15600,15602,15604,15606,15608,15610],{"class":3834,"line":3942},[3832,15601,4105],{"class":3845},[3832,15603,4108],{"class":3889},[3832,15605,9277],{"class":4042},[3832,15607,4114],{"class":3849},[3832,15609,6153],{"class":4117},[3832,15611,4267],{"class":3849},[3832,15613,15614,15616,15618,15620,15622,15624],{"class":3834,"line":3948},[3832,15615,6252],{"class":3853},[3832,15617,6255],{"class":4117},[3832,15619,4976],{"class":3849},[3832,15621,6260],{"class":3853},[3832,15623,9322],{"class":3869},[3832,15625,6266],{"class":3849},[3832,15627,15628,15630,15632,15634,15636,15638,15640],{"class":3834,"line":3953},[3832,15629,6288],{"class":4117},[3832,15631,4304],{"class":3853},[3832,15633,4307],{"class":3849},[3832,15635,4310],{"class":3853},[3832,15637,4313],{"class":3849},[3832,15639,4140],{"class":3889},[3832,15641,6301],{"class":3849},[3832,15643,15644],{"class":3834,"line":3959},[3832,15645,15646],{"class":3838},"        \u002F\u002F Query без аргументів — тип \u003CТипВідповіді, void>\n",[3832,15648,15649,15651,15653,15655,15657,15659,15661,15663,15665],{"class":3834,"line":3969},[3832,15650,9363],{"class":3853},[3832,15652,6314],{"class":3853},[3832,15654,4183],{"class":3849},[3832,15656,6319],{"class":4117},[3832,15658,5084],{"class":3849},[3832,15660,9374],{"class":3893},[3832,15662,6326],{"class":3849},[3832,15664,6329],{"class":3893},[3832,15666,6332],{"class":3849},[3832,15668,15669,15671,15673,15675,15677,15679],{"class":3834,"line":3986},[3832,15670,6337],{"class":4117},[3832,15672,4304],{"class":3853},[3832,15674,4137],{"class":3849},[3832,15676,4140],{"class":3889},[3832,15678,9393],{"class":3869},[3832,15680,4072],{"class":3849},[3832,15682,15683],{"class":3834,"line":4000},[3832,15684,6367],{"class":3849},[3832,15686,15687],{"class":3834,"line":4020},[3832,15688,6475],{"class":3849},[3832,15690,15691],{"class":3834,"line":4025},[3832,15692,4566],{"class":3849},[3832,15694,15695],{"class":3834,"line":4030},[3832,15696,3877],{"emptyLinePlaceholder":3876},[3832,15698,15699,15701,15703,15705,15707,15709],{"class":3834,"line":4036},[3832,15700,4105],{"class":3845},[3832,15702,4108],{"class":3889},[3832,15704,3850],{"class":3849},[3832,15706,9427],{"class":4042},[3832,15708,4748],{"class":3849},[3832,15710,9432],{"class":3853},[3801,15712,15713],{},[3770,15714,15715],{},"Використання у компоненті:",[3822,15717,15719],{"className":4592,"code":15718,"language":4594,"meta":3827,"style":3827},"function PostsScreen() {\n    \u002F\u002F Виклик без аргументів\n    const { data, isLoading, error } = useGetPostsQuery()\n    \n    if (isLoading) return \u003CActivityIndicator \u002F>\n    if (error) return \u003CText>Помилка завантаження\u003C\u002FText>\n    \n    return (\n        \u003CFlatList\n            data={data}\n            renderItem={({ item }) => \u003CText>{item.title}\u003C\u002FText>}\n        \u002F>\n    )\n}\n",[3829,15720,15721,15729,15734,15756,15760,15778,15804,15808,15814,15820,15832,15872,15876,15880],{"__ignoreMap":3827},[3832,15722,15723,15725,15727],{"class":3834,"line":3835},[3832,15724,7416],{"class":3889},[3832,15726,9901],{"class":4117},[3832,15728,4705],{"class":3849},[3832,15730,15731],{"class":3834,"line":3842},[3832,15732,15733],{"class":3838},"    \u002F\u002F Виклик без аргументів\n",[3832,15735,15736,15738,15740,15742,15744,15746,15748,15750,15752,15754],{"class":3834,"line":3873},[3832,15737,4710],{"class":3889},[3832,15739,3850],{"class":3849},[3832,15741,6565],{"class":4042},[3832,15743,3857],{"class":3849},[3832,15745,4371],{"class":4042},[3832,15747,3857],{"class":3849},[3832,15749,4386],{"class":4042},[3832,15751,4748],{"class":3849},[3832,15753,9427],{"class":4117},[3832,15755,4230],{"class":3849},[3832,15757,15758],{"class":3834,"line":3880},[3832,15759,4724],{"class":3849},[3832,15761,15762,15764,15766,15768,15770,15772,15774,15776],{"class":3834,"line":3886},[3832,15763,4821],{"class":3845},[3832,15765,4307],{"class":3849},[3832,15767,4371],{"class":3853},[3832,15769,4313],{"class":3849},[3832,15771,6600],{"class":3845},[3832,15773,4835],{"class":4834},[3832,15775,4645],{"class":3893},[3832,15777,4850],{"class":4834},[3832,15779,15780,15782,15784,15786,15788,15790,15792,15794,15796,15798,15800,15802],{"class":3834,"line":3900},[3832,15781,4821],{"class":3845},[3832,15783,4307],{"class":3849},[3832,15785,4386],{"class":3853},[3832,15787,4313],{"class":3849},[3832,15789,6600],{"class":3845},[3832,15791,4835],{"class":4834},[3832,15793,4635],{"class":3893},[3832,15795,4879],{"class":4834},[3832,15797,6627],{"class":3849},[3832,15799,4893],{"class":4834},[3832,15801,4635],{"class":3893},[3832,15803,4898],{"class":4834},[3832,15805,15806],{"class":3834,"line":3912},[3832,15807,4724],{"class":3849},[3832,15809,15810,15812],{"class":3834,"line":3922},[3832,15811,4911],{"class":3845},[3832,15813,4914],{"class":3849},[3832,15815,15816,15818],{"class":3834,"line":3932},[3832,15817,4919],{"class":4834},[3832,15819,4922],{"class":3893},[3832,15821,15822,15824,15826,15828,15830],{"class":3834,"line":3942},[3832,15823,4927],{"class":4840},[3832,15825,4844],{"class":3849},[3832,15827,4885],{"class":3889},[3832,15829,6565],{"class":3853},[3832,15831,3945],{"class":3889},[3832,15833,15834,15836,15838,15840,15842,15844,15846,15848,15850,15852,15854,15856,15858,15860,15862,15864,15866,15868,15870],{"class":3834,"line":3948},[3832,15835,4969],{"class":4840},[3832,15837,4844],{"class":3849},[3832,15839,4885],{"class":3889},[3832,15841,4976],{"class":4947},[3832,15843,4950],{"class":3853},[3832,15845,4981],{"class":4947},[3832,15847,4140],{"class":3889},[3832,15849,4835],{"class":4834},[3832,15851,4635],{"class":3893},[3832,15853,4879],{"class":4834},[3832,15855,4885],{"class":3889},[3832,15857,4950],{"class":3853},[3832,15859,4183],{"class":4947},[3832,15861,4998],{"class":3853},[3832,15863,4890],{"class":3889},[3832,15865,4893],{"class":4834},[3832,15867,4635],{"class":3893},[3832,15869,4879],{"class":4834},[3832,15871,3945],{"class":3889},[3832,15873,15874],{"class":3834,"line":3953},[3832,15875,5013],{"class":4834},[3832,15877,15878],{"class":3834,"line":3959},[3832,15879,5018],{"class":3849},[3832,15881,15882],{"class":3834,"line":3969},[3832,15883,3945],{"class":3849},[8569,15885,15886,15889],{},[3770,15887,15888],{},"Коли використовувати:"," Для запитів, які завжди повертають одні й ті ж дані для всіх користувачів (наприклад, список категорій, налаштувань застосунку, публічні дані).",[3809,15891,15893],{"id":15892},"рівень-2-get-запит-з-одним-параметром","Рівень 2: GET-запит з одним параметром",[3801,15895,15896],{},"Тепер отримаємо конкретний пост за ID:",[3822,15898,15900],{"className":3824,"code":15899,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fservices\u002Fapi.ts\nexport const api = createApi({\n    baseQuery: fetchBaseQuery({ baseUrl: 'https:\u002F\u002Fjsonplaceholder.typicode.com' }),\n    endpoints: (builder) => ({\n        \u002F\u002F Аргумент — число (ID поста)\n        getPostById: builder.query\u003CPost, number>({\n            query: (postId) => `\u002Fposts\u002F${postId}`,\n        }),\n    }),\n})\n\nexport const { useGetPostByIdQuery } = api\n",[3829,15901,15902,15906,15920,15934,15950,15955,15976,16004,16008,16012,16016,16020],{"__ignoreMap":3827},[3832,15903,15904],{"class":3834,"line":3835},[3832,15905,9193],{"class":3838},[3832,15907,15908,15910,15912,15914,15916,15918],{"class":3834,"line":3842},[3832,15909,4105],{"class":3845},[3832,15911,4108],{"class":3889},[3832,15913,9277],{"class":4042},[3832,15915,4114],{"class":3849},[3832,15917,6153],{"class":4117},[3832,15919,4267],{"class":3849},[3832,15921,15922,15924,15926,15928,15930,15932],{"class":3834,"line":3873},[3832,15923,6252],{"class":3853},[3832,15925,6255],{"class":4117},[3832,15927,4976],{"class":3849},[3832,15929,6260],{"class":3853},[3832,15931,9322],{"class":3869},[3832,15933,6266],{"class":3849},[3832,15935,15936,15938,15940,15942,15944,15946,15948],{"class":3834,"line":3880},[3832,15937,6288],{"class":4117},[3832,15939,4304],{"class":3853},[3832,15941,4307],{"class":3849},[3832,15943,4310],{"class":3853},[3832,15945,4313],{"class":3849},[3832,15947,4140],{"class":3889},[3832,15949,6301],{"class":3849},[3832,15951,15952],{"class":3834,"line":3886},[3832,15953,15954],{"class":3838},"        \u002F\u002F Аргумент — число (ID поста)\n",[3832,15956,15957,15960,15962,15964,15966,15968,15970,15972,15974],{"class":3834,"line":3900},[3832,15958,15959],{"class":3853},"        getPostById:",[3832,15961,6314],{"class":3853},[3832,15963,4183],{"class":3849},[3832,15965,6319],{"class":4117},[3832,15967,5084],{"class":3849},[3832,15969,9374],{"class":3893},[3832,15971,3857],{"class":3849},[3832,15973,5663],{"class":3893},[3832,15975,6332],{"class":3849},[3832,15977,15978,15980,15982,15984,15987,15989,15991,15994,15996,15998,16000,16002],{"class":3834,"line":3912},[3832,15979,6337],{"class":4117},[3832,15981,4304],{"class":3853},[3832,15983,4307],{"class":3849},[3832,15985,15986],{"class":3853},"postId",[3832,15988,4313],{"class":3849},[3832,15990,4140],{"class":3889},[3832,15992,15993],{"class":3869}," `\u002Fposts\u002F",[3832,15995,11249],{"class":3889},[3832,15997,15986],{"class":3853},[3832,15999,4890],{"class":3889},[3832,16001,11514],{"class":3869},[3832,16003,4072],{"class":3849},[3832,16005,16006],{"class":3834,"line":3922},[3832,16007,6367],{"class":3849},[3832,16009,16010],{"class":3834,"line":3932},[3832,16011,6475],{"class":3849},[3832,16013,16014],{"class":3834,"line":3942},[3832,16015,4566],{"class":3849},[3832,16017,16018],{"class":3834,"line":3948},[3832,16019,3877],{"emptyLinePlaceholder":3876},[3832,16021,16022,16024,16026,16028,16031,16033],{"class":3834,"line":3953},[3832,16023,4105],{"class":3845},[3832,16025,4108],{"class":3889},[3832,16027,3850],{"class":3849},[3832,16029,16030],{"class":4042},"useGetPostByIdQuery",[3832,16032,4748],{"class":3849},[3832,16034,9432],{"class":3853},[3801,16036,16037],{},[3770,16038,16039],{},"Використання:",[3822,16041,16043],{"className":4592,"code":16042,"language":4594,"meta":3827,"style":3827},"function PostDetailScreen({ route }) {\n    const postId = route.params.id\n    \n    \u002F\u002F Передаємо ID як аргумент\n    const { data: post, isLoading } = useGetPostByIdQuery(postId)\n    \n    if (isLoading) return \u003CActivityIndicator \u002F>\n    \n    return (\n        \u003CView>\n            \u003CText style={styles.title}>{post?.title}\u003C\u002FText>\n            \u003CText>{post?.body}\u003C\u002FText>\n        \u003C\u002FView>\n    )\n}\n",[3829,16044,16045,16059,16080,16084,16089,16116,16120,16138,16142,16148,16156,16194,16218,16226,16230],{"__ignoreMap":3827},[3832,16046,16047,16049,16052,16054,16057],{"class":3834,"line":3835},[3832,16048,7416],{"class":3889},[3832,16050,16051],{"class":4117}," PostDetailScreen",[3832,16053,4976],{"class":3849},[3832,16055,16056],{"class":3853},"route",[3832,16058,8353],{"class":3849},[3832,16060,16061,16063,16066,16068,16070,16072,16075,16077],{"class":3834,"line":3842},[3832,16062,4710],{"class":3889},[3832,16064,16065],{"class":4042}," postId",[3832,16067,4114],{"class":3849},[3832,16069,16056],{"class":3853},[3832,16071,4183],{"class":3849},[3832,16073,16074],{"class":3853},"params",[3832,16076,4183],{"class":3849},[3832,16078,16079],{"class":3853},"id\n",[3832,16081,16082],{"class":3834,"line":3873},[3832,16083,4724],{"class":3849},[3832,16085,16086],{"class":3834,"line":3880},[3832,16087,16088],{"class":3838},"    \u002F\u002F Передаємо ID як аргумент\n",[3832,16090,16091,16093,16095,16097,16099,16102,16104,16106,16108,16110,16112,16114],{"class":3834,"line":3886},[3832,16092,4710],{"class":3889},[3832,16094,3850],{"class":3849},[3832,16096,6565],{"class":3853},[3832,16098,3906],{"class":3849},[3832,16100,16101],{"class":4042},"post",[3832,16103,3857],{"class":3849},[3832,16105,4371],{"class":4042},[3832,16107,4748],{"class":3849},[3832,16109,16030],{"class":4117},[3832,16111,4162],{"class":3849},[3832,16113,15986],{"class":3853},[3832,16115,4168],{"class":3849},[3832,16117,16118],{"class":3834,"line":3900},[3832,16119,4724],{"class":3849},[3832,16121,16122,16124,16126,16128,16130,16132,16134,16136],{"class":3834,"line":3912},[3832,16123,4821],{"class":3845},[3832,16125,4307],{"class":3849},[3832,16127,4371],{"class":3853},[3832,16129,4313],{"class":3849},[3832,16131,6600],{"class":3845},[3832,16133,4835],{"class":4834},[3832,16135,4645],{"class":3893},[3832,16137,4850],{"class":4834},[3832,16139,16140],{"class":3834,"line":3922},[3832,16141,4724],{"class":3849},[3832,16143,16144,16146],{"class":3834,"line":3932},[3832,16145,4911],{"class":3845},[3832,16147,4914],{"class":3849},[3832,16149,16150,16152,16154],{"class":3834,"line":3942},[3832,16151,4919],{"class":4834},[3832,16153,4630],{"class":3893},[3832,16155,4898],{"class":4834},[3832,16157,16158,16160,16162,16164,16166,16168,16170,16172,16174,16176,16178,16180,16182,16184,16186,16188,16190,16192],{"class":3834,"line":3948},[3832,16159,7532],{"class":4834},[3832,16161,4635],{"class":3893},[3832,16163,8467],{"class":4840},[3832,16165,4844],{"class":3849},[3832,16167,4885],{"class":3889},[3832,16169,9970],{"class":3853},[3832,16171,4183],{"class":4947},[3832,16173,4998],{"class":3853},[3832,16175,4890],{"class":3889},[3832,16177,4879],{"class":4834},[3832,16179,4885],{"class":3889},[3832,16181,16101],{"class":3853},[3832,16183,11188],{"class":4947},[3832,16185,4998],{"class":3853},[3832,16187,4890],{"class":3889},[3832,16189,4893],{"class":4834},[3832,16191,4635],{"class":3893},[3832,16193,4898],{"class":4834},[3832,16195,16196,16198,16200,16202,16204,16206,16208,16210,16212,16214,16216],{"class":3834,"line":3953},[3832,16197,7532],{"class":4834},[3832,16199,4635],{"class":3893},[3832,16201,4879],{"class":4834},[3832,16203,4885],{"class":3889},[3832,16205,16101],{"class":3853},[3832,16207,11188],{"class":4947},[3832,16209,10327],{"class":3853},[3832,16211,4890],{"class":3889},[3832,16213,4893],{"class":4834},[3832,16215,4635],{"class":3893},[3832,16217,4898],{"class":4834},[3832,16219,16220,16222,16224],{"class":3834,"line":3959},[3832,16221,7596],{"class":4834},[3832,16223,4630],{"class":3893},[3832,16225,4898],{"class":4834},[3832,16227,16228],{"class":3834,"line":3969},[3832,16229,5018],{"class":3849},[3832,16231,16232],{"class":3834,"line":3986},[3832,16233,3945],{"class":3849},[3801,16235,16236],{},[3770,16237,16238],{},"Що відбувається під капотом:",[5430,16240,16241,16245,16251,16255,16261,16265,16270,16274],{},[3809,16242,16244],{"id":16243},"компонент-рендериться-з-postid-5","Компонент рендериться з postId = 5",[3801,16246,16247,16248],{},"RTK Query створює унікальний ключ кешу: ",[3829,16249,16250],{},"getPostById(5)",[3809,16252,16254],{"id":16253},"перевіряє-кеш","Перевіряє кеш",[3801,16256,16257,16258,16260],{},"Чи є дані для ",[3829,16259,16250],{}," у пам'яті?",[3809,16262,16264],{"id":16263},"якщо-немає-робить-запит","Якщо немає — робить запит",[3801,16266,16267],{},[3829,16268,16269],{},"GET \u002Fposts\u002F5",[3809,16271,16273],{"id":16272},"зберігає-результат","Зберігає результат",[3801,16275,16276,16277,16280],{},"Наступний виклик ",[3829,16278,16279],{},"useGetPostByIdQuery(5)"," поверне дані з кешу миттєво!",[6795,16282,16283,16285,16286,16289,16290,16293],{},[3770,16284,9171],{}," Якщо ви викликаєте ",[3829,16287,16288],{},"useGetPostByIdQuery(10)"," — це ",[3770,16291,16292],{},"інший"," кеш. RTK Query робить окремий запит для кожного унікального аргументу.",[3809,16295,16297],{"id":16296},"рівень-3-get-запит-зі-складними-параметрами-фільтри","Рівень 3: GET-запит зі складними параметрами (фільтри)",[3801,16299,16300],{},"У реальних застосунках часто потрібно передавати кілька параметрів — фільтри, сортування, пагінацію. Для цього використовуємо об'єкт:",[3822,16302,16304],{"className":3824,"code":16303,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fservices\u002FtripsApi.ts\ninterface Trip {\n    id: string\n    title: string\n    region: string\n    startDate: string\n}\n\n\u002F\u002F Інтерфейс для параметрів фільтрації\ninterface GetTripsParams {\n    region?: string\n    search?: string\n    sortBy?: 'date' | 'title'\n    limit?: number\n}\n\nexport const tripsApi = createApi({\n    baseQuery: fetchBaseQuery({ baseUrl: 'http:\u002F\u002Flocalhost:3000' }),\n    endpoints: (builder) => ({\n        getTrips: builder.query\u003CTrip[], GetTripsParams | void>({\n            query: (params) => {\n                \u002F\u002F Якщо параметрів немає — просто повертаємо URL\n                if (!params) return '\u002Ftrips'\n                \n                \u002F\u002F Будуємо query string з параметрів\n                const searchParams = new URLSearchParams()\n                \n                if (params.region) searchParams.set('region', params.region)\n                if (params.search) searchParams.set('q', params.search)\n                if (params.sortBy) searchParams.set('_sort', params.sortBy)\n                if (params.limit) searchParams.set('_limit', params.limit.toString())\n                \n                return `\u002Ftrips?${searchParams.toString()}`\n            },\n        }),\n    }),\n})\n\nexport const { useGetTripsQuery } = tripsApi\n",[3829,16305,16306,16310,16318,16326,16334,16342,16350,16354,16358,16363,16372,16381,16390,16405,16414,16418,16422,16436,16450,16466,16491,16507,16512,16527,16531,16536,16552,16556,16592,16628,16664,16704,16708,16731,16735,16739,16743,16747,16751],{"__ignoreMap":3827},[3832,16307,16308],{"class":3834,"line":3835},[3832,16309,11022],{"class":3838},[3832,16311,16312,16314,16316],{"class":3834,"line":3842},[3832,16313,3890],{"class":3889},[3832,16315,3894],{"class":3893},[3832,16317,3897],{"class":3849},[3832,16319,16320,16322,16324],{"class":3834,"line":3873},[3832,16321,3903],{"class":3853},[3832,16323,3906],{"class":3849},[3832,16325,3909],{"class":3893},[3832,16327,16328,16330,16332],{"class":3834,"line":3880},[3832,16329,3915],{"class":3853},[3832,16331,3906],{"class":3849},[3832,16333,3909],{"class":3893},[3832,16335,16336,16338,16340],{"class":3834,"line":3886},[3832,16337,3925],{"class":3853},[3832,16339,3906],{"class":3849},[3832,16341,3909],{"class":3893},[3832,16343,16344,16346,16348],{"class":3834,"line":3900},[3832,16345,3935],{"class":3853},[3832,16347,3906],{"class":3849},[3832,16349,3909],{"class":3893},[3832,16351,16352],{"class":3834,"line":3912},[3832,16353,3945],{"class":3849},[3832,16355,16356],{"class":3834,"line":3922},[3832,16357,3877],{"emptyLinePlaceholder":3876},[3832,16359,16360],{"class":3834,"line":3932},[3832,16361,16362],{"class":3838},"\u002F\u002F Інтерфейс для параметрів фільтрації\n",[3832,16364,16365,16367,16370],{"class":3834,"line":3942},[3832,16366,3890],{"class":3889},[3832,16368,16369],{"class":3893}," GetTripsParams",[3832,16371,3897],{"class":3849},[3832,16373,16374,16376,16379],{"class":3834,"line":3948},[3832,16375,3925],{"class":3853},[3832,16377,16378],{"class":3849},"?: ",[3832,16380,3909],{"class":3893},[3832,16382,16383,16386,16388],{"class":3834,"line":3953},[3832,16384,16385],{"class":3853},"    search",[3832,16387,16378],{"class":3849},[3832,16389,3909],{"class":3893},[3832,16391,16392,16395,16397,16400,16402],{"class":3834,"line":3959},[3832,16393,16394],{"class":3853},"    sortBy",[3832,16396,16378],{"class":3849},[3832,16398,16399],{"class":3869},"'date'",[3832,16401,4011],{"class":3849},[3832,16403,16404],{"class":3869},"'title'\n",[3832,16406,16407,16410,16412],{"class":3834,"line":3969},[3832,16408,16409],{"class":3853},"    limit",[3832,16411,16378],{"class":3849},[3832,16413,9238],{"class":3893},[3832,16415,16416],{"class":3834,"line":3986},[3832,16417,3945],{"class":3849},[3832,16419,16420],{"class":3834,"line":4000},[3832,16421,3877],{"emptyLinePlaceholder":3876},[3832,16423,16424,16426,16428,16430,16432,16434],{"class":3834,"line":4020},[3832,16425,4105],{"class":3845},[3832,16427,4108],{"class":3889},[3832,16429,6231],{"class":4042},[3832,16431,4114],{"class":3849},[3832,16433,6153],{"class":4117},[3832,16435,4267],{"class":3849},[3832,16437,16438,16440,16442,16444,16446,16448],{"class":3834,"line":4025},[3832,16439,6252],{"class":3853},[3832,16441,6255],{"class":4117},[3832,16443,4976],{"class":3849},[3832,16445,6260],{"class":3853},[3832,16447,6263],{"class":3869},[3832,16449,6266],{"class":3849},[3832,16451,16452,16454,16456,16458,16460,16462,16464],{"class":3834,"line":4030},[3832,16453,6288],{"class":4117},[3832,16455,4304],{"class":3853},[3832,16457,4307],{"class":3849},[3832,16459,4310],{"class":3853},[3832,16461,4313],{"class":3849},[3832,16463,4140],{"class":3889},[3832,16465,6301],{"class":3849},[3832,16467,16468,16470,16472,16474,16476,16478,16480,16482,16485,16487,16489],{"class":3834,"line":4036},[3832,16469,6311],{"class":3853},[3832,16471,6314],{"class":3853},[3832,16473,4183],{"class":3849},[3832,16475,6319],{"class":4117},[3832,16477,5084],{"class":3849},[3832,16479,3977],{"class":3893},[3832,16481,6326],{"class":3849},[3832,16483,16484],{"class":3893},"GetTripsParams",[3832,16486,4011],{"class":3849},[3832,16488,6329],{"class":3893},[3832,16490,6332],{"class":3849},[3832,16492,16493,16495,16497,16499,16501,16503,16505],{"class":3834,"line":4054},[3832,16494,6337],{"class":4117},[3832,16496,4304],{"class":3853},[3832,16498,4307],{"class":3849},[3832,16500,16074],{"class":3853},[3832,16502,4313],{"class":3849},[3832,16504,4140],{"class":3889},[3832,16506,3897],{"class":3849},[3832,16508,16509],{"class":3834,"line":4063},[3832,16510,16511],{"class":3838},"                \u002F\u002F Якщо параметрів немає — просто повертаємо URL\n",[3832,16513,16514,16516,16518,16520,16522,16524],{"class":3834,"line":4075},[3832,16515,15035],{"class":3845},[3832,16517,4177],{"class":3849},[3832,16519,16074],{"class":3853},[3832,16521,4313],{"class":3849},[3832,16523,6600],{"class":3845},[3832,16525,16526],{"class":3869}," '\u002Ftrips'\n",[3832,16528,16529],{"class":3834,"line":4086},[3832,16530,14921],{"class":3849},[3832,16532,16533],{"class":3834,"line":4091},[3832,16534,16535],{"class":3838},"                \u002F\u002F Будуємо query string з параметрів\n",[3832,16537,16538,16540,16543,16545,16547,16550],{"class":3834,"line":4096},[3832,16539,14926],{"class":3889},[3832,16541,16542],{"class":4042}," searchParams",[3832,16544,4114],{"class":3849},[3832,16546,7494],{"class":3889},[3832,16548,16549],{"class":4117}," URLSearchParams",[3832,16551,4230],{"class":3849},[3832,16553,16554],{"class":3834,"line":4102},[3832,16555,14921],{"class":3849},[3832,16557,16558,16560,16562,16564,16566,16568,16570,16573,16575,16577,16579,16582,16584,16586,16588,16590],{"class":3834,"line":4123},[3832,16559,15035],{"class":3845},[3832,16561,4307],{"class":3849},[3832,16563,16074],{"class":3853},[3832,16565,4183],{"class":3849},[3832,16567,7456],{"class":3853},[3832,16569,4313],{"class":3849},[3832,16571,16572],{"class":3853},"searchParams",[3832,16574,4183],{"class":3849},[3832,16576,8928],{"class":4117},[3832,16578,4162],{"class":3849},[3832,16580,16581],{"class":3869},"'region'",[3832,16583,3857],{"class":3849},[3832,16585,16074],{"class":3853},[3832,16587,4183],{"class":3849},[3832,16589,7456],{"class":3853},[3832,16591,4168],{"class":3849},[3832,16593,16594,16596,16598,16600,16602,16605,16607,16609,16611,16613,16615,16618,16620,16622,16624,16626],{"class":3834,"line":4131},[3832,16595,15035],{"class":3845},[3832,16597,4307],{"class":3849},[3832,16599,16074],{"class":3853},[3832,16601,4183],{"class":3849},[3832,16603,16604],{"class":3853},"search",[3832,16606,4313],{"class":3849},[3832,16608,16572],{"class":3853},[3832,16610,4183],{"class":3849},[3832,16612,8928],{"class":4117},[3832,16614,4162],{"class":3849},[3832,16616,16617],{"class":3869},"'q'",[3832,16619,3857],{"class":3849},[3832,16621,16074],{"class":3853},[3832,16623,4183],{"class":3849},[3832,16625,16604],{"class":3853},[3832,16627,4168],{"class":3849},[3832,16629,16630,16632,16634,16636,16638,16641,16643,16645,16647,16649,16651,16654,16656,16658,16660,16662],{"class":3834,"line":4145},[3832,16631,15035],{"class":3845},[3832,16633,4307],{"class":3849},[3832,16635,16074],{"class":3853},[3832,16637,4183],{"class":3849},[3832,16639,16640],{"class":3853},"sortBy",[3832,16642,4313],{"class":3849},[3832,16644,16572],{"class":3853},[3832,16646,4183],{"class":3849},[3832,16648,8928],{"class":4117},[3832,16650,4162],{"class":3849},[3832,16652,16653],{"class":3869},"'_sort'",[3832,16655,3857],{"class":3849},[3832,16657,16074],{"class":3853},[3832,16659,4183],{"class":3849},[3832,16661,16640],{"class":3853},[3832,16663,4168],{"class":3849},[3832,16665,16666,16668,16670,16672,16674,16677,16679,16681,16683,16685,16687,16690,16692,16694,16696,16698,16700,16702],{"class":3834,"line":4171},[3832,16667,15035],{"class":3845},[3832,16669,4307],{"class":3849},[3832,16671,16074],{"class":3853},[3832,16673,4183],{"class":3849},[3832,16675,16676],{"class":3853},"limit",[3832,16678,4313],{"class":3849},[3832,16680,16572],{"class":3853},[3832,16682,4183],{"class":3849},[3832,16684,8928],{"class":4117},[3832,16686,4162],{"class":3849},[3832,16688,16689],{"class":3869},"'_limit'",[3832,16691,3857],{"class":3849},[3832,16693,16074],{"class":3853},[3832,16695,4183],{"class":3849},[3832,16697,16676],{"class":3853},[3832,16699,4183],{"class":3849},[3832,16701,10136],{"class":4117},[3832,16703,4801],{"class":3849},[3832,16705,16706],{"class":3834,"line":4192},[3832,16707,14921],{"class":3849},[3832,16709,16710,16713,16716,16718,16720,16722,16724,16726,16728],{"class":3834,"line":4211},[3832,16711,16712],{"class":3845},"                return",[3832,16714,16715],{"class":3869}," `\u002Ftrips?",[3832,16717,11249],{"class":3889},[3832,16719,16572],{"class":3853},[3832,16721,4183],{"class":4947},[3832,16723,10136],{"class":4117},[3832,16725,10139],{"class":4947},[3832,16727,4890],{"class":3889},[3832,16729,16730],{"class":3869},"`\n",[3832,16732,16733],{"class":3834,"line":4217},[3832,16734,13923],{"class":3849},[3832,16736,16737],{"class":3834,"line":4233},[3832,16738,6367],{"class":3849},[3832,16740,16741],{"class":3834,"line":4239},[3832,16742,6475],{"class":3849},[3832,16744,16745],{"class":3834,"line":4244},[3832,16746,4566],{"class":3849},[3832,16748,16749],{"class":3834,"line":4249},[3832,16750,3877],{"emptyLinePlaceholder":3876},[3832,16752,16753,16755,16757,16759,16761,16763],{"class":3834,"line":4255},[3832,16754,4105],{"class":3845},[3832,16756,4108],{"class":3889},[3832,16758,3850],{"class":3849},[3832,16760,6499],{"class":4042},[3832,16762,4748],{"class":3849},[3832,16764,6509],{"class":3853},[3801,16766,16767],{},[3770,16768,16769],{},"Використання з різними фільтрами:",[3822,16771,16773],{"className":4592,"code":16772,"language":4594,"meta":3827,"style":3827},"function TripsListScreen() {\n    const [region, setRegion] = useState\u003Cstring>('all')\n    const [search, setSearch] = useState('')\n    \n    \u002F\u002F Передаємо об'єкт з параметрами\n    const { data: trips, isLoading } = useGetTripsQuery({\n        region: region !== 'all' ? region : undefined,\n        search: search || undefined,\n        limit: 20,\n    })\n    \n    return (\n        \u003CView>\n            \u003CPicker value={region} onValueChange={setRegion}>\n                \u003CPicker.Item label=\"Усі регіони\" value=\"all\" \u002F>\n                \u003CPicker.Item label=\"Європа\" value=\"europe\" \u002F>\n                \u003CPicker.Item label=\"Азія\" value=\"asia\" \u002F>\n            \u003C\u002FPicker>\n            \n            \u003CTextInput\n                placeholder=\"Пошук...\"\n                value={search}\n                onChangeText={setSearch}\n            \u002F>\n            \n            \u003CFlatList\n                data={trips}\n                renderItem={({ item }) => \u003CTripCard trip={item} \u002F>}\n            \u002F>\n        \u003C\u002FView>\n    )\n}\n",[3829,16774,16775,16783,16811,16834,16838,16843,16865,16889,16903,16912,16916,16920,16926,16934,16965,16989,17011,17033,17041,17045,17052,17061,17073,17085,17089,17093,17099,17112,17150,17154,17162,17166],{"__ignoreMap":3827},[3832,16776,16777,16779,16781],{"class":3834,"line":3835},[3832,16778,7416],{"class":3889},[3832,16780,4702],{"class":4117},[3832,16782,4705],{"class":3849},[3832,16784,16785,16787,16789,16791,16793,16795,16797,16799,16801,16803,16806,16809],{"class":3834,"line":3842},[3832,16786,4710],{"class":3889},[3832,16788,6274],{"class":3849},[3832,16790,7456],{"class":4042},[3832,16792,3857],{"class":3849},[3832,16794,7461],{"class":4042},[3832,16796,7437],{"class":3849},[3832,16798,7440],{"class":4117},[3832,16800,5084],{"class":3849},[3832,16802,4008],{"class":3893},[3832,16804,16805],{"class":3849},">(",[3832,16807,16808],{"class":3869},"'all'",[3832,16810,4168],{"class":3849},[3832,16812,16813,16815,16817,16819,16821,16824,16826,16828,16830,16832],{"class":3834,"line":3873},[3832,16814,4710],{"class":3889},[3832,16816,6274],{"class":3849},[3832,16818,16604],{"class":4042},[3832,16820,3857],{"class":3849},[3832,16822,16823],{"class":4042},"setSearch",[3832,16825,7437],{"class":3849},[3832,16827,7440],{"class":4117},[3832,16829,4162],{"class":3849},[3832,16831,7445],{"class":3869},[3832,16833,4168],{"class":3849},[3832,16835,16836],{"class":3834,"line":3880},[3832,16837,4724],{"class":3849},[3832,16839,16840],{"class":3834,"line":3886},[3832,16841,16842],{"class":3838},"    \u002F\u002F Передаємо об'єкт з параметрами\n",[3832,16844,16845,16847,16849,16851,16853,16855,16857,16859,16861,16863],{"class":3834,"line":3900},[3832,16846,4710],{"class":3889},[3832,16848,3850],{"class":3849},[3832,16850,6565],{"class":3853},[3832,16852,3906],{"class":3849},[3832,16854,4458],{"class":4042},[3832,16856,3857],{"class":3849},[3832,16858,4371],{"class":4042},[3832,16860,4748],{"class":3849},[3832,16862,6499],{"class":4117},[3832,16864,4267],{"class":3849},[3832,16866,16867,16870,16873,16876,16878,16880,16882,16884,16887],{"class":3834,"line":3912},[3832,16868,16869],{"class":3853},"        region:",[3832,16871,16872],{"class":3853}," region",[3832,16874,16875],{"class":3849}," !== ",[3832,16877,16808],{"class":3869},[3832,16879,7055],{"class":3849},[3832,16881,7456],{"class":3853},[3832,16883,7061],{"class":3849},[3832,16885,16886],{"class":3889},"undefined",[3832,16888,4072],{"class":3849},[3832,16890,16891,16894,16897,16899,16901],{"class":3834,"line":3922},[3832,16892,16893],{"class":3853},"        search:",[3832,16895,16896],{"class":3853}," search",[3832,16898,4546],{"class":3849},[3832,16900,16886],{"class":3889},[3832,16902,4072],{"class":3849},[3832,16904,16905,16908,16910],{"class":3834,"line":3932},[3832,16906,16907],{"class":3853},"        limit:",[3832,16909,10440],{"class":5726},[3832,16911,4072],{"class":3849},[3832,16913,16914],{"class":3834,"line":3942},[3832,16915,5951],{"class":3849},[3832,16917,16918],{"class":3834,"line":3948},[3832,16919,4724],{"class":3849},[3832,16921,16922,16924],{"class":3834,"line":3953},[3832,16923,4911],{"class":3845},[3832,16925,4914],{"class":3849},[3832,16927,16928,16930,16932],{"class":3834,"line":3959},[3832,16929,4919],{"class":4834},[3832,16931,4630],{"class":3893},[3832,16933,4898],{"class":4834},[3832,16935,16936,16938,16941,16944,16946,16948,16950,16952,16955,16957,16959,16961,16963],{"class":3834,"line":3969},[3832,16937,7532],{"class":4834},[3832,16939,16940],{"class":3893},"Picker",[3832,16942,16943],{"class":4840}," value",[3832,16945,4844],{"class":3849},[3832,16947,4885],{"class":3889},[3832,16949,7456],{"class":3853},[3832,16951,4890],{"class":3889},[3832,16953,16954],{"class":4840}," onValueChange",[3832,16956,4844],{"class":3849},[3832,16958,4885],{"class":3889},[3832,16960,7461],{"class":3853},[3832,16962,4890],{"class":3889},[3832,16964,4898],{"class":4834},[3832,16966,16967,16969,16972,16975,16977,16980,16982,16984,16987],{"class":3834,"line":3986},[3832,16968,9984],{"class":4834},[3832,16970,16971],{"class":3893},"Picker.Item",[3832,16973,16974],{"class":4840}," label",[3832,16976,4844],{"class":3849},[3832,16978,16979],{"class":3869},"\"Усі регіони\"",[3832,16981,16943],{"class":4840},[3832,16983,4844],{"class":3849},[3832,16985,16986],{"class":3869},"\"all\"",[3832,16988,4850],{"class":4834},[3832,16990,16991,16993,16995,16997,16999,17002,17004,17006,17009],{"class":3834,"line":4000},[3832,16992,9984],{"class":4834},[3832,16994,16971],{"class":3893},[3832,16996,16974],{"class":4840},[3832,16998,4844],{"class":3849},[3832,17000,17001],{"class":3869},"\"Європа\"",[3832,17003,16943],{"class":4840},[3832,17005,4844],{"class":3849},[3832,17007,17008],{"class":3869},"\"europe\"",[3832,17010,4850],{"class":4834},[3832,17012,17013,17015,17017,17019,17021,17024,17026,17028,17031],{"class":3834,"line":4020},[3832,17014,9984],{"class":4834},[3832,17016,16971],{"class":3893},[3832,17018,16974],{"class":4840},[3832,17020,4844],{"class":3849},[3832,17022,17023],{"class":3869},"\"Азія\"",[3832,17025,16943],{"class":4840},[3832,17027,4844],{"class":3849},[3832,17029,17030],{"class":3869},"\"asia\"",[3832,17032,4850],{"class":4834},[3832,17034,17035,17037,17039],{"class":3834,"line":4025},[3832,17036,10039],{"class":4834},[3832,17038,16940],{"class":3893},[3832,17040,4898],{"class":4834},[3832,17042,17043],{"class":3834,"line":4030},[3832,17044,8518],{"class":3849},[3832,17046,17047,17049],{"class":3834,"line":4036},[3832,17048,7532],{"class":4834},[3832,17050,17051],{"class":3893},"TextInput\n",[3832,17053,17054,17056,17058],{"class":3834,"line":4054},[3832,17055,7571],{"class":4840},[3832,17057,4844],{"class":3849},[3832,17059,17060],{"class":3869},"\"Пошук...\"\n",[3832,17062,17063,17065,17067,17069,17071],{"class":3834,"line":4063},[3832,17064,7543],{"class":4840},[3832,17066,4844],{"class":3849},[3832,17068,4885],{"class":3889},[3832,17070,16604],{"class":3853},[3832,17072,3945],{"class":3889},[3832,17074,17075,17077,17079,17081,17083],{"class":3834,"line":4075},[3832,17076,7558],{"class":4840},[3832,17078,4844],{"class":3849},[3832,17080,4885],{"class":3889},[3832,17082,16823],{"class":3853},[3832,17084,3945],{"class":3889},[3832,17086,17087],{"class":3834,"line":4086},[3832,17088,7581],{"class":4834},[3832,17090,17091],{"class":3834,"line":4091},[3832,17092,8518],{"class":3849},[3832,17094,17095,17097],{"class":3834,"line":4096},[3832,17096,7532],{"class":4834},[3832,17098,4922],{"class":3893},[3832,17100,17101,17104,17106,17108,17110],{"class":3834,"line":4102},[3832,17102,17103],{"class":4840},"                data",[3832,17105,4844],{"class":3849},[3832,17107,4885],{"class":3889},[3832,17109,4458],{"class":3853},[3832,17111,3945],{"class":3889},[3832,17113,17114,17117,17119,17121,17123,17125,17127,17129,17131,17134,17137,17139,17141,17143,17145,17148],{"class":3834,"line":4123},[3832,17115,17116],{"class":4840},"                renderItem",[3832,17118,4844],{"class":3849},[3832,17120,4885],{"class":3889},[3832,17122,4976],{"class":4947},[3832,17124,4950],{"class":3853},[3832,17126,4981],{"class":4947},[3832,17128,4140],{"class":3889},[3832,17130,4835],{"class":4834},[3832,17132,17133],{"class":3893},"TripCard",[3832,17135,17136],{"class":4840}," trip",[3832,17138,4844],{"class":3849},[3832,17140,4885],{"class":3889},[3832,17142,4950],{"class":3853},[3832,17144,4890],{"class":3889},[3832,17146,17147],{"class":4834}," \u002F>",[3832,17149,3945],{"class":3889},[3832,17151,17152],{"class":3834,"line":4131},[3832,17153,7581],{"class":4834},[3832,17155,17156,17158,17160],{"class":3834,"line":4145},[3832,17157,7596],{"class":4834},[3832,17159,4630],{"class":3893},[3832,17161,4898],{"class":4834},[3832,17163,17164],{"class":3834,"line":4171},[3832,17165,5018],{"class":3849},[3832,17167,17168],{"class":3834,"line":4192},[3832,17169,3945],{"class":3849},[3801,17171,17172],{},[3770,17173,17174],{},"Як RTK Query кешує різні комбінації параметрів:",[3822,17176,17178],{"className":3824,"code":17177,"language":3826,"meta":3827,"style":3827},"useGetTripsQuery({ region: 'europe' })        \u002F\u002F Кеш #1\nuseGetTripsQuery({ region: 'asia' })          \u002F\u002F Кеш #2\nuseGetTripsQuery({ region: 'europe', limit: 10 })  \u002F\u002F Кеш #3\nuseGetTripsQuery()                            \u002F\u002F Кеш #4 (без параметрів)\n",[3829,17179,17180,17198,17215,17239],{"__ignoreMap":3827},[3832,17181,17182,17184,17186,17189,17192,17195],{"class":3834,"line":3835},[3832,17183,6499],{"class":4117},[3832,17185,4976],{"class":3849},[3832,17187,17188],{"class":3853},"region:",[3832,17190,17191],{"class":3869}," 'europe'",[3832,17193,17194],{"class":3849}," })        ",[3832,17196,17197],{"class":3838},"\u002F\u002F Кеш #1\n",[3832,17199,17200,17202,17204,17206,17209,17212],{"class":3834,"line":3842},[3832,17201,6499],{"class":4117},[3832,17203,4976],{"class":3849},[3832,17205,17188],{"class":3853},[3832,17207,17208],{"class":3869}," 'asia'",[3832,17210,17211],{"class":3849}," })          ",[3832,17213,17214],{"class":3838},"\u002F\u002F Кеш #2\n",[3832,17216,17217,17219,17221,17223,17225,17227,17230,17233,17236],{"class":3834,"line":3873},[3832,17218,6499],{"class":4117},[3832,17220,4976],{"class":3849},[3832,17222,17188],{"class":3853},[3832,17224,17191],{"class":3869},[3832,17226,3857],{"class":3849},[3832,17228,17229],{"class":3853},"limit:",[3832,17231,17232],{"class":5726}," 10",[3832,17234,17235],{"class":3849}," })  ",[3832,17237,17238],{"class":3838},"\u002F\u002F Кеш #3\n",[3832,17240,17241,17243,17246],{"class":3834,"line":3880},[3832,17242,6499],{"class":4117},[3832,17244,17245],{"class":3849},"()                            ",[3832,17247,17248],{"class":3838},"\u002F\u002F Кеш #4 (без параметрів)\n",[3801,17250,17251],{},"Кожна унікальна комбінація параметрів створює окремий запис у кеші!",[6083,17253,17254,17259,17265],{},[3801,17255,17256,17258],{},[3770,17257,5420],{}," Якщо користувач швидко вводить текст у пошук, кожна літера створить новий запит:",[3822,17260,17263],{"className":17261,"code":17262,"language":13010},[13008],"\"П\"  → GET \u002Ftrips?q=П\n\"Па\" → GET \u002Ftrips?q=Па  \n\"Пар\" → GET \u002Ftrips?q=Пар\n\"Пари\" → GET \u002Ftrips?q=Пари\n\"Париж\" → GET \u002Ftrips?q=Париж\n",[3829,17264,17262],{"__ignoreMap":3827},[3801,17266,17267],{},"5 запитів за секунду — це надто багато! Рішення — дебаунс (debounce), про який поговоримо нижче.",[3809,17269,17271],{"id":17270},"рівень-4-трансформація-відповіді-transformresponse","Рівень 4: Трансформація відповіді (transformResponse)",[3801,17273,17274],{},"Іноді сервер повертає дані у незручному форматі, і їх треба обробити перед збереженням у кеш:",[3822,17276,17278],{"className":3824,"code":17277,"language":3826,"meta":3827,"style":3827},"\u002F\u002F Сервер повертає:\n{\n    \"status\": \"success\",\n    \"data\": {\n        \"items\": [...],\n        \"total\": 42,\n        \"page\": 1\n    }\n}\n\n\u002F\u002F Але нам потрібен лише масив items\n",[3829,17279,17280,17285,17289,17301,17309,17319,17331,17341,17345,17349,17353],{"__ignoreMap":3827},[3832,17281,17282],{"class":3834,"line":3835},[3832,17283,17284],{"class":3838},"\u002F\u002F Сервер повертає:\n",[3832,17286,17287],{"class":3834,"line":3842},[3832,17288,11782],{"class":3849},[3832,17290,17291,17294,17296,17299],{"class":3834,"line":3873},[3832,17292,17293],{"class":3869},"    \"status\"",[3832,17295,3906],{"class":3849},[3832,17297,17298],{"class":3869},"\"success\"",[3832,17300,4072],{"class":3849},[3832,17302,17303,17306],{"class":3834,"line":3880},[3832,17304,17305],{"class":3869},"    \"data\"",[3832,17307,17308],{"class":3849},": {\n",[3832,17310,17311,17314,17316],{"class":3834,"line":3886},[3832,17312,17313],{"class":3869},"        \"items\"",[3832,17315,4304],{"class":3853},[3832,17317,17318],{"class":3849}," [...],\n",[3832,17320,17321,17324,17326,17329],{"class":3834,"line":3900},[3832,17322,17323],{"class":3869},"        \"total\"",[3832,17325,4304],{"class":3853},[3832,17327,17328],{"class":5726}," 42",[3832,17330,4072],{"class":3849},[3832,17332,17333,17336,17338],{"class":3834,"line":3912},[3832,17334,17335],{"class":3869},"        \"page\"",[3832,17337,4304],{"class":3853},[3832,17339,17340],{"class":5726}," 1\n",[3832,17342,17343],{"class":3834,"line":3922},[3832,17344,4236],{"class":3849},[3832,17346,17347],{"class":3834,"line":3932},[3832,17348,3945],{"class":3849},[3832,17350,17351],{"class":3834,"line":3942},[3832,17352,3877],{"emptyLinePlaceholder":3876},[3832,17354,17355],{"class":3834,"line":3948},[3832,17356,17357],{"class":3838},"\u002F\u002F Але нам потрібен лише масив items\n",[3801,17359,17360],{},[3770,17361,17362,17363,4304],{},"Рішення через ",[3829,17364,17365],{},"transformResponse",[3822,17367,17369],{"className":3824,"code":17368,"language":3826,"meta":3827,"style":3827},"export const api = createApi({\n    endpoints: (builder) => ({\n        getTrips: builder.query\u003CTrip[], void>({\n            query: () => '\u002Ftrips',\n            \n            \u002F\u002F Трансформуємо відповідь перед збереженням у кеш\n            transformResponse: (response: { status: string; data: { items: Trip[] } }) => {\n                console.log('📦 Сирі дані з сервера:', response)\n                \n                \u002F\u002F Витягуємо лише масив items\n                return response.data.items\n            },\n        }),\n    }),\n})\n",[3829,17370,17371,17385,17401,17421,17435,17439,17444,17483,17502,17506,17511,17526,17530,17534,17538],{"__ignoreMap":3827},[3832,17372,17373,17375,17377,17379,17381,17383],{"class":3834,"line":3835},[3832,17374,4105],{"class":3845},[3832,17376,4108],{"class":3889},[3832,17378,9277],{"class":4042},[3832,17380,4114],{"class":3849},[3832,17382,6153],{"class":4117},[3832,17384,4267],{"class":3849},[3832,17386,17387,17389,17391,17393,17395,17397,17399],{"class":3834,"line":3842},[3832,17388,6288],{"class":4117},[3832,17390,4304],{"class":3853},[3832,17392,4307],{"class":3849},[3832,17394,4310],{"class":3853},[3832,17396,4313],{"class":3849},[3832,17398,4140],{"class":3889},[3832,17400,6301],{"class":3849},[3832,17402,17403,17405,17407,17409,17411,17413,17415,17417,17419],{"class":3834,"line":3873},[3832,17404,6311],{"class":3853},[3832,17406,6314],{"class":3853},[3832,17408,4183],{"class":3849},[3832,17410,6319],{"class":4117},[3832,17412,5084],{"class":3849},[3832,17414,3977],{"class":3893},[3832,17416,6326],{"class":3849},[3832,17418,6329],{"class":3893},[3832,17420,6332],{"class":3849},[3832,17422,17423,17425,17427,17429,17431,17433],{"class":3834,"line":3880},[3832,17424,6337],{"class":4117},[3832,17426,4304],{"class":3853},[3832,17428,4137],{"class":3849},[3832,17430,4140],{"class":3889},[3832,17432,6346],{"class":3869},[3832,17434,4072],{"class":3849},[3832,17436,17437],{"class":3834,"line":3886},[3832,17438,8518],{"class":3849},[3832,17440,17441],{"class":3834,"line":3900},[3832,17442,17443],{"class":3838},"            \u002F\u002F Трансформуємо відповідь перед збереженням у кеш\n",[3832,17445,17446,17449,17451,17453,17455,17457,17459,17461,17463,17465,17467,17469,17472,17474,17476,17479,17481],{"class":3834,"line":3912},[3832,17447,17448],{"class":4117},"            transformResponse",[3832,17450,4304],{"class":3853},[3832,17452,4307],{"class":3849},[3832,17454,4180],{"class":3853},[3832,17456,11801],{"class":3849},[3832,17458,13800],{"class":3853},[3832,17460,3906],{"class":3849},[3832,17462,4008],{"class":3893},[3832,17464,12378],{"class":3849},[3832,17466,6565],{"class":3853},[3832,17468,11801],{"class":3849},[3832,17470,17471],{"class":3853},"items",[3832,17473,3906],{"class":3849},[3832,17475,3977],{"class":3893},[3832,17477,17478],{"class":3849},"[] } }) ",[3832,17480,4140],{"class":3889},[3832,17482,3897],{"class":3849},[3832,17484,17485,17487,17489,17491,17493,17496,17498,17500],{"class":3834,"line":3922},[3832,17486,14905],{"class":3853},[3832,17488,4183],{"class":3849},[3832,17490,7989],{"class":4117},[3832,17492,4162],{"class":3849},[3832,17494,17495],{"class":3869},"'📦 Сирі дані з сервера:'",[3832,17497,3857],{"class":3849},[3832,17499,4180],{"class":3853},[3832,17501,4168],{"class":3849},[3832,17503,17504],{"class":3834,"line":3932},[3832,17505,14921],{"class":3849},[3832,17507,17508],{"class":3834,"line":3942},[3832,17509,17510],{"class":3838},"                \u002F\u002F Витягуємо лише масив items\n",[3832,17512,17513,17515,17517,17519,17521,17523],{"class":3834,"line":3948},[3832,17514,16712],{"class":3845},[3832,17516,4151],{"class":3853},[3832,17518,4183],{"class":3849},[3832,17520,6565],{"class":3853},[3832,17522,4183],{"class":3849},[3832,17524,17525],{"class":3853},"items\n",[3832,17527,17528],{"class":3834,"line":3953},[3832,17529,13923],{"class":3849},[3832,17531,17532],{"class":3834,"line":3959},[3832,17533,6367],{"class":3849},[3832,17535,17536],{"class":3834,"line":3969},[3832,17537,6475],{"class":3849},[3832,17539,17540],{"class":3834,"line":3986},[3832,17541,4566],{"class":3849},[3801,17543,17544,17545,17547,17548,17551],{},"Тепер у компоненті ",[3829,17546,6565],{}," буде одразу масивом ",[3829,17549,17550],{},"Trip[]",", а не вкладеним об'єктом!",[3801,17553,17554],{},[3770,17555,17556,17557,4304],{},"Інші приклади використання ",[3829,17558,17365],{},[6860,17560,17561,17668,17749],{},[3822,17562,17565],{"className":3824,"code":17563,"filename":17564,"language":3826,"meta":3827,"style":3827},"transformResponse: (response: Trip[]) => {\n    \u002F\u002F Сортуємо за датою (найновіші спочатку)\n    return response.sort((a, b) => \n        new Date(b.startDate).getTime() - new Date(a.startDate).getTime()\n    )\n}\n","Сортування на клієнті",[3829,17566,17567,17586,17591,17618,17660,17664],{"__ignoreMap":3827},[3832,17568,17569,17571,17573,17575,17577,17579,17582,17584],{"class":3834,"line":3835},[3832,17570,17365],{"class":5204},[3832,17572,5208],{"class":3849},[3832,17574,4180],{"class":3853},[3832,17576,3906],{"class":3849},[3832,17578,3977],{"class":3893},[3832,17580,17581],{"class":3849},"[]) ",[3832,17583,4140],{"class":3889},[3832,17585,3897],{"class":3849},[3832,17587,17588],{"class":3834,"line":3842},[3832,17589,17590],{"class":3838},"    \u002F\u002F Сортуємо за датою (найновіші спочатку)\n",[3832,17592,17593,17595,17597,17599,17602,17604,17607,17609,17612,17614,17616],{"class":3834,"line":3873},[3832,17594,4911],{"class":3845},[3832,17596,4151],{"class":3853},[3832,17598,4183],{"class":3849},[3832,17600,17601],{"class":4117},"sort",[3832,17603,4753],{"class":3849},[3832,17605,17606],{"class":3853},"a",[3832,17608,3857],{"class":3849},[3832,17610,17611],{"class":3853},"b",[3832,17613,4313],{"class":3849},[3832,17615,4140],{"class":3889},[3832,17617,7538],{"class":3849},[3832,17619,17620,17623,17625,17627,17629,17631,17634,17636,17639,17642,17644,17646,17648,17650,17652,17654,17656,17658],{"class":3834,"line":3880},[3832,17621,17622],{"class":3889},"        new",[3832,17624,7497],{"class":4117},[3832,17626,4162],{"class":3849},[3832,17628,17611],{"class":3853},[3832,17630,4183],{"class":3849},[3832,17632,17633],{"class":3853},"startDate",[3832,17635,5621],{"class":3849},[3832,17637,17638],{"class":4117},"getTime",[3832,17640,17641],{"class":3849},"() - ",[3832,17643,7494],{"class":3889},[3832,17645,7497],{"class":4117},[3832,17647,4162],{"class":3849},[3832,17649,17606],{"class":3853},[3832,17651,4183],{"class":3849},[3832,17653,17633],{"class":3853},[3832,17655,5621],{"class":3849},[3832,17657,17638],{"class":4117},[3832,17659,4230],{"class":3849},[3832,17661,17662],{"class":3834,"line":3886},[3832,17663,5018],{"class":3849},[3832,17665,17666],{"class":3834,"line":3900},[3832,17667,3945],{"class":3849},[3822,17669,17672],{"className":3824,"code":17670,"filename":17671,"language":3826,"meta":3827,"style":3827},"transformResponse: (response: Trip[]) => {\n    \u002F\u002F Видаляємо поїздки з порожніми назвами\n    return response.filter(trip => trip.title && trip.title.trim().length > 0)\n}\n","Фільтрація недійсних даних",[3829,17673,17674,17692,17697,17745],{"__ignoreMap":3827},[3832,17675,17676,17678,17680,17682,17684,17686,17688,17690],{"class":3834,"line":3835},[3832,17677,17365],{"class":5204},[3832,17679,5208],{"class":3849},[3832,17681,4180],{"class":3853},[3832,17683,3906],{"class":3849},[3832,17685,3977],{"class":3893},[3832,17687,17581],{"class":3849},[3832,17689,4140],{"class":3889},[3832,17691,3897],{"class":3849},[3832,17693,17694],{"class":3834,"line":3842},[3832,17695,17696],{"class":3838},"    \u002F\u002F Видаляємо поїздки з порожніми назвами\n",[3832,17698,17699,17701,17703,17705,17708,17710,17712,17714,17716,17718,17720,17722,17724,17726,17728,17730,17733,17735,17738,17740,17743],{"class":3834,"line":3873},[3832,17700,4911],{"class":3845},[3832,17702,4151],{"class":3853},[3832,17704,4183],{"class":3849},[3832,17706,17707],{"class":4117},"filter",[3832,17709,4162],{"class":3849},[3832,17711,8412],{"class":3853},[3832,17713,11121],{"class":3889},[3832,17715,17136],{"class":3853},[3832,17717,4183],{"class":3849},[3832,17719,4998],{"class":3853},[3832,17721,13789],{"class":3849},[3832,17723,8412],{"class":3853},[3832,17725,4183],{"class":3849},[3832,17727,4998],{"class":3853},[3832,17729,4183],{"class":3849},[3832,17731,17732],{"class":4117},"trim",[3832,17734,9620],{"class":3849},[3832,17736,17737],{"class":3853},"length",[3832,17739,5763],{"class":3849},[3832,17741,17742],{"class":5726},"0",[3832,17744,4168],{"class":3849},[3832,17746,17747],{"class":3834,"line":3880},[3832,17748,3945],{"class":3849},[3822,17750,17753],{"className":3824,"code":17751,"filename":17752,"language":3826,"meta":3827,"style":3827},"transformResponse: (response: Trip[]) => {\n    return response.map(trip => ({\n        ...trip,\n        \u002F\u002F Додаємо обчислюване поле \"чи поїздка активна\"\n        isActive: new Date(trip.startDate) > new Date(),\n        \u002F\u002F Форматована дата\n        displayDate: new Date(trip.startDate).toLocaleDateString('uk-UA'),\n    }))\n}\n","Додавання обчислюваних полів",[3829,17754,17755,17773,17792,17801,17806,17832,17837,17866,17871],{"__ignoreMap":3827},[3832,17756,17757,17759,17761,17763,17765,17767,17769,17771],{"class":3834,"line":3835},[3832,17758,17365],{"class":5204},[3832,17760,5208],{"class":3849},[3832,17762,4180],{"class":3853},[3832,17764,3906],{"class":3849},[3832,17766,3977],{"class":3893},[3832,17768,17581],{"class":3849},[3832,17770,4140],{"class":3889},[3832,17772,3897],{"class":3849},[3832,17774,17775,17777,17779,17781,17784,17786,17788,17790],{"class":3834,"line":3842},[3832,17776,4911],{"class":3845},[3832,17778,4151],{"class":3853},[3832,17780,4183],{"class":3849},[3832,17782,17783],{"class":4117},"map",[3832,17785,4162],{"class":3849},[3832,17787,8412],{"class":3853},[3832,17789,11121],{"class":3889},[3832,17791,6301],{"class":3849},[3832,17793,17794,17797,17799],{"class":3834,"line":3873},[3832,17795,17796],{"class":3849},"        ...",[3832,17798,8412],{"class":3853},[3832,17800,4072],{"class":3849},[3832,17802,17803],{"class":3834,"line":3880},[3832,17804,17805],{"class":3838},"        \u002F\u002F Додаємо обчислюване поле \"чи поїздка активна\"\n",[3832,17807,17808,17811,17813,17815,17817,17819,17821,17823,17826,17828,17830],{"class":3834,"line":3886},[3832,17809,17810],{"class":3853},"        isActive:",[3832,17812,4198],{"class":3889},[3832,17814,7497],{"class":4117},[3832,17816,4162],{"class":3849},[3832,17818,8412],{"class":3853},[3832,17820,4183],{"class":3849},[3832,17822,17633],{"class":3853},[3832,17824,17825],{"class":3849},") > ",[3832,17827,7494],{"class":3889},[3832,17829,7497],{"class":4117},[3832,17831,11385],{"class":3849},[3832,17833,17834],{"class":3834,"line":3900},[3832,17835,17836],{"class":3838},"        \u002F\u002F Форматована дата\n",[3832,17838,17839,17842,17844,17846,17848,17850,17852,17854,17856,17859,17861,17864],{"class":3834,"line":3912},[3832,17840,17841],{"class":3853},"        displayDate:",[3832,17843,4198],{"class":3889},[3832,17845,7497],{"class":4117},[3832,17847,4162],{"class":3849},[3832,17849,8412],{"class":3853},[3832,17851,4183],{"class":3849},[3832,17853,17633],{"class":3853},[3832,17855,5621],{"class":3849},[3832,17857,17858],{"class":4117},"toLocaleDateString",[3832,17860,4162],{"class":3849},[3832,17862,17863],{"class":3869},"'uk-UA'",[3832,17865,5165],{"class":3849},[3832,17867,17868],{"class":3834,"line":3922},[3832,17869,17870],{"class":3849},"    }))\n",[3832,17872,17873],{"class":3834,"line":3932},[3832,17874,3945],{"class":3849},[3809,17876,17878],{"id":17877},"розуміння-результату-хука-що-повертає-usequery","Розуміння результату хука: Що повертає useQuery",[3801,17880,17881],{},"Кожен Query-хук повертає об'єкт з багатьма корисними полями. Розберемо їх детально:",[3822,17883,17885],{"className":3824,"code":17884,"language":3826,"meta":3827,"style":3827},"const {\n    data,              \u002F\u002F Дані з кешу або сервера\n    error,             \u002F\u002F Об'єкт помилки (якщо щось пішло не так)\n    isLoading,         \u002F\u002F true ТІЛЬКИ при першому завантаженні\n    isFetching,        \u002F\u002F true при будь-якому запиті (включно з фоновим)\n    isSuccess,         \u002F\u002F true коли дані успішно завантажені\n    isError,           \u002F\u002F true при помилці\n    refetch,           \u002F\u002F Функція для примусового оновлення\n    currentData,       \u002F\u002F Дані поточного запиту (може бути undefined)\n    originalArgs,      \u002F\u002F Аргументи, з якими було викликано хук\n} = useGetTripsQuery(params)\n",[3829,17886,17887,17893,17903,17913,17923,17934,17944,17955,17965,17976,17987],{"__ignoreMap":3827},[3832,17888,17889,17891],{"class":3834,"line":3835},[3832,17890,4039],{"class":3889},[3832,17892,3897],{"class":3849},[3832,17894,17895,17897,17900],{"class":3834,"line":3842},[3832,17896,13064],{"class":4042},[3832,17898,17899],{"class":3849},",              ",[3832,17901,17902],{"class":3838},"\u002F\u002F Дані з кешу або сервера\n",[3832,17904,17905,17907,17910],{"class":3834,"line":3873},[3832,17906,4003],{"class":4042},[3832,17908,17909],{"class":3849},",             ",[3832,17911,17912],{"class":3838},"\u002F\u002F Об'єкт помилки (якщо щось пішло не так)\n",[3832,17914,17915,17917,17920],{"class":3834,"line":3880},[3832,17916,3989],{"class":4042},[3832,17918,17919],{"class":3849},",         ",[3832,17921,17922],{"class":3838},"\u002F\u002F true ТІЛЬКИ при першому завантаженні\n",[3832,17924,17925,17928,17931],{"class":3834,"line":3886},[3832,17926,17927],{"class":4042},"    isFetching",[3832,17929,17930],{"class":3849},",        ",[3832,17932,17933],{"class":3838},"\u002F\u002F true при будь-якому запиті (включно з фоновим)\n",[3832,17935,17936,17939,17941],{"class":3834,"line":3900},[3832,17937,17938],{"class":4042},"    isSuccess",[3832,17940,17919],{"class":3849},[3832,17942,17943],{"class":3838},"\u002F\u002F true коли дані успішно завантажені\n",[3832,17945,17946,17949,17952],{"class":3834,"line":3912},[3832,17947,17948],{"class":4042},"    isError",[3832,17950,17951],{"class":3849},",           ",[3832,17953,17954],{"class":3838},"\u002F\u002F true при помилці\n",[3832,17956,17957,17960,17962],{"class":3834,"line":3922},[3832,17958,17959],{"class":4042},"    refetch",[3832,17961,17951],{"class":3849},[3832,17963,17964],{"class":3838},"\u002F\u002F Функція для примусового оновлення\n",[3832,17966,17967,17970,17973],{"class":3834,"line":3932},[3832,17968,17969],{"class":4042},"    currentData",[3832,17971,17972],{"class":3849},",       ",[3832,17974,17975],{"class":3838},"\u002F\u002F Дані поточного запиту (може бути undefined)\n",[3832,17977,17978,17981,17984],{"class":3834,"line":3942},[3832,17979,17980],{"class":4042},"    originalArgs",[3832,17982,17983],{"class":3849},",      ",[3832,17985,17986],{"class":3838},"\u002F\u002F Аргументи, з якими було викликано хук\n",[3832,17988,17989,17992,17994,17996,17998],{"class":3834,"line":3948},[3832,17990,17991],{"class":3849},"} = ",[3832,17993,6499],{"class":4117},[3832,17995,4162],{"class":3849},[3832,17997,16074],{"class":3853},[3832,17999,4168],{"class":3849},[3801,18001,18002],{},[3770,18003,18004,18005,18007,18008,4304],{},"Різниця між ",[3829,18006,4371],{}," та ",[3829,18009,9744],{},[5457,18011,18012,18133,18299],{},[5460,18013,18015],{"label":18014},"Сценарій 1: Перше завантаження",[3822,18016,18018],{"className":4592,"code":18017,"language":4594,"meta":3827,"style":3827},"\u002F\u002F Користувач вперше відкриває екран\nconst { data, isLoading, isFetching } = useGetTripsQuery()\n\nconsole.log(isLoading)   \u002F\u002F true ← немає жодних даних\nconsole.log(isFetching)  \u002F\u002F true ← запит виконується\nconsole.log(data)        \u002F\u002F undefined ← ще нічого не завантажилось\n\n\u002F\u002F ✅ Показуємо повноекранний skeleton\nif (isLoading) return \u003CSkeletonLoader \u002F>\n",[3829,18019,18020,18025,18047,18051,18069,18086,18104,18108,18113],{"__ignoreMap":3827},[3832,18021,18022],{"class":3834,"line":3835},[3832,18023,18024],{"class":3838},"\u002F\u002F Користувач вперше відкриває екран\n",[3832,18026,18027,18029,18031,18033,18035,18037,18039,18041,18043,18045],{"class":3834,"line":3842},[3832,18028,4039],{"class":3889},[3832,18030,3850],{"class":3849},[3832,18032,6565],{"class":4042},[3832,18034,3857],{"class":3849},[3832,18036,4371],{"class":4042},[3832,18038,3857],{"class":3849},[3832,18040,9744],{"class":4042},[3832,18042,4748],{"class":3849},[3832,18044,6499],{"class":4117},[3832,18046,4230],{"class":3849},[3832,18048,18049],{"class":3834,"line":3873},[3832,18050,3877],{"emptyLinePlaceholder":3876},[3832,18052,18053,18055,18057,18059,18061,18063,18066],{"class":3834,"line":3880},[3832,18054,7984],{"class":3853},[3832,18056,4183],{"class":3849},[3832,18058,7989],{"class":4117},[3832,18060,4162],{"class":3849},[3832,18062,4371],{"class":3853},[3832,18064,18065],{"class":3849},")   ",[3832,18067,18068],{"class":3838},"\u002F\u002F true ← немає жодних даних\n",[3832,18070,18071,18073,18075,18077,18079,18081,18083],{"class":3834,"line":3886},[3832,18072,7984],{"class":3853},[3832,18074,4183],{"class":3849},[3832,18076,7989],{"class":4117},[3832,18078,4162],{"class":3849},[3832,18080,9744],{"class":3853},[3832,18082,7793],{"class":3849},[3832,18084,18085],{"class":3838},"\u002F\u002F true ← запит виконується\n",[3832,18087,18088,18090,18092,18094,18096,18098,18101],{"class":3834,"line":3900},[3832,18089,7984],{"class":3853},[3832,18091,4183],{"class":3849},[3832,18093,7989],{"class":4117},[3832,18095,4162],{"class":3849},[3832,18097,6565],{"class":3853},[3832,18099,18100],{"class":3849},")        ",[3832,18102,18103],{"class":3838},"\u002F\u002F undefined ← ще нічого не завантажилось\n",[3832,18105,18106],{"class":3834,"line":3912},[3832,18107,3877],{"emptyLinePlaceholder":3876},[3832,18109,18110],{"class":3834,"line":3922},[3832,18111,18112],{"class":3838},"\u002F\u002F ✅ Показуємо повноекранний skeleton\n",[3832,18114,18115,18118,18120,18122,18124,18126,18128,18131],{"class":3834,"line":3932},[3832,18116,18117],{"class":3845},"if",[3832,18119,4307],{"class":3849},[3832,18121,4371],{"class":3853},[3832,18123,4313],{"class":3849},[3832,18125,6600],{"class":3845},[3832,18127,4835],{"class":4834},[3832,18129,18130],{"class":3893},"SkeletonLoader",[3832,18132,4850],{"class":4834},[5460,18134,18136],{"label":18135},"Сценарій 2: Фонове оновлення",[3822,18137,18139],{"className":4592,"code":18138,"language":4594,"meta":3827,"style":3827},"\u002F\u002F Користувач повертається з іншого екрана\n\u002F\u002F RTK Query вирішує оновити дані (refetchOnFocus: true)\n\nconst { data, isLoading, isFetching } = useGetTripsQuery()\n\nconsole.log(isLoading)   \u002F\u002F false ← є старі дані з кешу\nconsole.log(isFetching)  \u002F\u002F true ← запит виконується у фоні\nconsole.log(data)        \u002F\u002F [...] ← показуємо старі дані поки оновлюються нові\n\n\u002F\u002F ✅ Показуємо дані + маленький індикатор оновлення\nreturn (\n    \u003C>\n        {isFetching && \u003CTopBarRefreshIndicator \u002F>}\n        \u003CFlatList data={data} \u002F>\n    \u003C\u002F>\n)\n",[3829,18140,18141,18146,18151,18155,18177,18181,18198,18215,18232,18236,18241,18247,18252,18271,18290,18295],{"__ignoreMap":3827},[3832,18142,18143],{"class":3834,"line":3835},[3832,18144,18145],{"class":3838},"\u002F\u002F Користувач повертається з іншого екрана\n",[3832,18147,18148],{"class":3834,"line":3842},[3832,18149,18150],{"class":3838},"\u002F\u002F RTK Query вирішує оновити дані (refetchOnFocus: true)\n",[3832,18152,18153],{"class":3834,"line":3873},[3832,18154,3877],{"emptyLinePlaceholder":3876},[3832,18156,18157,18159,18161,18163,18165,18167,18169,18171,18173,18175],{"class":3834,"line":3880},[3832,18158,4039],{"class":3889},[3832,18160,3850],{"class":3849},[3832,18162,6565],{"class":4042},[3832,18164,3857],{"class":3849},[3832,18166,4371],{"class":4042},[3832,18168,3857],{"class":3849},[3832,18170,9744],{"class":4042},[3832,18172,4748],{"class":3849},[3832,18174,6499],{"class":4117},[3832,18176,4230],{"class":3849},[3832,18178,18179],{"class":3834,"line":3886},[3832,18180,3877],{"emptyLinePlaceholder":3876},[3832,18182,18183,18185,18187,18189,18191,18193,18195],{"class":3834,"line":3900},[3832,18184,7984],{"class":3853},[3832,18186,4183],{"class":3849},[3832,18188,7989],{"class":4117},[3832,18190,4162],{"class":3849},[3832,18192,4371],{"class":3853},[3832,18194,18065],{"class":3849},[3832,18196,18197],{"class":3838},"\u002F\u002F false ← є старі дані з кешу\n",[3832,18199,18200,18202,18204,18206,18208,18210,18212],{"class":3834,"line":3912},[3832,18201,7984],{"class":3853},[3832,18203,4183],{"class":3849},[3832,18205,7989],{"class":4117},[3832,18207,4162],{"class":3849},[3832,18209,9744],{"class":3853},[3832,18211,7793],{"class":3849},[3832,18213,18214],{"class":3838},"\u002F\u002F true ← запит виконується у фоні\n",[3832,18216,18217,18219,18221,18223,18225,18227,18229],{"class":3834,"line":3922},[3832,18218,7984],{"class":3853},[3832,18220,4183],{"class":3849},[3832,18222,7989],{"class":4117},[3832,18224,4162],{"class":3849},[3832,18226,6565],{"class":3853},[3832,18228,18100],{"class":3849},[3832,18230,18231],{"class":3838},"\u002F\u002F [...] ← показуємо старі дані поки оновлюються нові\n",[3832,18233,18234],{"class":3834,"line":3932},[3832,18235,3877],{"emptyLinePlaceholder":3876},[3832,18237,18238],{"class":3834,"line":3942},[3832,18239,18240],{"class":3838},"\u002F\u002F ✅ Показуємо дані + маленький індикатор оновлення\n",[3832,18242,18243,18245],{"class":3834,"line":3948},[3832,18244,6600],{"class":3845},[3832,18246,4914],{"class":3849},[3832,18248,18249],{"class":3834,"line":3953},[3832,18250,18251],{"class":4834},"    \u003C>\n",[3832,18253,18254,18257,18259,18262,18264,18267,18269],{"class":3834,"line":3959},[3832,18255,18256],{"class":3889},"        {",[3832,18258,9744],{"class":3853},[3832,18260,18261],{"class":3849}," &&",[3832,18263,4835],{"class":4834},[3832,18265,18266],{"class":3893},"TopBarRefreshIndicator",[3832,18268,17147],{"class":4834},[3832,18270,3945],{"class":3889},[3832,18272,18273,18275,18277,18280,18282,18284,18286,18288],{"class":3834,"line":3969},[3832,18274,4919],{"class":4834},[3832,18276,4640],{"class":3893},[3832,18278,18279],{"class":4840}," data",[3832,18281,4844],{"class":3849},[3832,18283,4885],{"class":3889},[3832,18285,6565],{"class":3853},[3832,18287,4890],{"class":3889},[3832,18289,4850],{"class":4834},[3832,18291,18292],{"class":3834,"line":3986},[3832,18293,18294],{"class":4834},"    \u003C\u002F>\n",[3832,18296,18297],{"class":3834,"line":4000},[3832,18298,4168],{"class":3849},[5460,18300,18302],{"label":18301},"Сценарій 3: Pull-to-Refresh",[3822,18303,18305],{"className":4592,"code":18304,"language":4594,"meta":3827,"style":3827},"\u002F\u002F Користувач тягне список вниз (Pull-to-Refresh)\n\nconst { data, isLoading, isFetching, refetch } = useGetTripsQuery()\n\nconsole.log(isLoading)   \u002F\u002F false ← дані вже є\nconsole.log(isFetching)  \u002F\u002F true ← запит запущено через refetch()\n\n\u002F\u002F ✅ RefreshControl показує індикатор\nreturn (\n    \u003CFlatList\n        data={data}\n        refreshControl={\n            \u003CRefreshControl \n                refreshing={isFetching} \n                onRefresh={refetch}\n            \u002F>\n        }\n    \u002F>\n)\n",[3829,18306,18307,18312,18316,18343,18347,18364,18381,18385,18390,18396,18403,18416,18425,18434,18449,18462,18466,18470,18475],{"__ignoreMap":3827},[3832,18308,18309],{"class":3834,"line":3835},[3832,18310,18311],{"class":3838},"\u002F\u002F Користувач тягне список вниз (Pull-to-Refresh)\n",[3832,18313,18314],{"class":3834,"line":3842},[3832,18315,3877],{"emptyLinePlaceholder":3876},[3832,18317,18318,18320,18322,18324,18326,18328,18330,18332,18334,18337,18339,18341],{"class":3834,"line":3873},[3832,18319,4039],{"class":3889},[3832,18321,3850],{"class":3849},[3832,18323,6565],{"class":4042},[3832,18325,3857],{"class":3849},[3832,18327,4371],{"class":4042},[3832,18329,3857],{"class":3849},[3832,18331,9744],{"class":4042},[3832,18333,3857],{"class":3849},[3832,18335,18336],{"class":4042},"refetch",[3832,18338,4748],{"class":3849},[3832,18340,6499],{"class":4117},[3832,18342,4230],{"class":3849},[3832,18344,18345],{"class":3834,"line":3880},[3832,18346,3877],{"emptyLinePlaceholder":3876},[3832,18348,18349,18351,18353,18355,18357,18359,18361],{"class":3834,"line":3886},[3832,18350,7984],{"class":3853},[3832,18352,4183],{"class":3849},[3832,18354,7989],{"class":4117},[3832,18356,4162],{"class":3849},[3832,18358,4371],{"class":3853},[3832,18360,18065],{"class":3849},[3832,18362,18363],{"class":3838},"\u002F\u002F false ← дані вже є\n",[3832,18365,18366,18368,18370,18372,18374,18376,18378],{"class":3834,"line":3900},[3832,18367,7984],{"class":3853},[3832,18369,4183],{"class":3849},[3832,18371,7989],{"class":4117},[3832,18373,4162],{"class":3849},[3832,18375,9744],{"class":3853},[3832,18377,7793],{"class":3849},[3832,18379,18380],{"class":3838},"\u002F\u002F true ← запит запущено через refetch()\n",[3832,18382,18383],{"class":3834,"line":3912},[3832,18384,3877],{"emptyLinePlaceholder":3876},[3832,18386,18387],{"class":3834,"line":3922},[3832,18388,18389],{"class":3838},"\u002F\u002F ✅ RefreshControl показує індикатор\n",[3832,18391,18392,18394],{"class":3834,"line":3932},[3832,18393,6600],{"class":3845},[3832,18395,4914],{"class":3849},[3832,18397,18398,18401],{"class":3834,"line":3942},[3832,18399,18400],{"class":4834},"    \u003C",[3832,18402,4922],{"class":3893},[3832,18404,18405,18408,18410,18412,18414],{"class":3834,"line":3948},[3832,18406,18407],{"class":4840},"        data",[3832,18409,4844],{"class":3849},[3832,18411,4885],{"class":3889},[3832,18413,6565],{"class":3853},[3832,18415,3945],{"class":3889},[3832,18417,18418,18421,18423],{"class":3834,"line":3953},[3832,18419,18420],{"class":4840},"        refreshControl",[3832,18422,4844],{"class":3849},[3832,18424,11782],{"class":3889},[3832,18426,18427,18429,18432],{"class":3834,"line":3959},[3832,18428,7532],{"class":4834},[3832,18430,18431],{"class":3893},"RefreshControl",[3832,18433,7538],{"class":4947},[3832,18435,18436,18439,18441,18443,18445,18447],{"class":3834,"line":3969},[3832,18437,18438],{"class":4840},"                refreshing",[3832,18440,4844],{"class":3849},[3832,18442,4885],{"class":3889},[3832,18444,9744],{"class":3853},[3832,18446,4890],{"class":3889},[3832,18448,7538],{"class":4947},[3832,18450,18451,18454,18456,18458,18460],{"class":3834,"line":3986},[3832,18452,18453],{"class":4840},"                onRefresh",[3832,18455,4844],{"class":3849},[3832,18457,4885],{"class":3889},[3832,18459,18336],{"class":3853},[3832,18461,3945],{"class":3889},[3832,18463,18464],{"class":3834,"line":4000},[3832,18465,7581],{"class":4834},[3832,18467,18468],{"class":3834,"line":4020},[3832,18469,4214],{"class":3889},[3832,18471,18472],{"class":3834,"line":4025},[3832,18473,18474],{"class":4834},"    \u002F>\n",[3832,18476,18477],{"class":3834,"line":4030},[3832,18478,4168],{"class":3849},[3801,18480,18481],{},[3770,18482,18483],{},"Правильна обробка станів у компоненті:",[3822,18485,18487],{"className":4592,"code":18486,"language":4594,"meta":3827,"style":3827},"function TripsListScreen() {\n    const { data, isLoading, isFetching, isError, error, refetch } = useGetTripsQuery()\n\n    \u002F\u002F 1. ПОВНОЕКРАННИЙ ЛОАДЕР: перше завантаження (немає даних)\n    if (isLoading) {\n        return (\n            \u003CView style={styles.center}>\n                \u003CActivityIndicator size=\"large\" \u002F>\n                \u003CText>Завантаження поїздок...\u003C\u002FText>\n            \u003C\u002FView>\n        )\n    }\n\n    \u002F\u002F 2. ЕКРАН ПОМИЛКИ: не вдалося завантажити\n    if (isError) {\n        return (\n            \u003CView style={styles.center}>\n                \u003CText style={styles.errorText}>\n                    Помилка: {error?.toString()}\n                \u003C\u002FText>\n                \u003CButton title=\"Спробувати знову\" onPress={refetch} \u002F>\n            \u003C\u002FView>\n        )\n    }\n\n    \u002F\u002F 3. РОБОЧИЙ СТАН: показуємо дані\n    return (\n        \u003CView style={styles.container}>\n            {\u002F* Тонкий індикатор фонового оновлення *\u002F}\n            {isFetching && !isLoading && (\n                \u003CView style={styles.topBar}>\n                    \u003CActivityIndicator size=\"small\" \u002F>\n                    \u003CText style={styles.topBarText}>Оновлення...\u003C\u002FText>\n                \u003C\u002FView>\n            )}\n            \n            \u003CFlatList\n                data={data}\n                keyExtractor={(item) => item.id}\n                renderItem={({ item }) => \u003CTripCard trip={item} \u002F>}\n                \n                {\u002F* Pull-to-Refresh *\u002F}\n                refreshControl={\n                    \u003CRefreshControl \n                        refreshing={isFetching && !isLoading}\n                        onRefresh={refetch}\n                        tintColor=\"#3b82f6\"\n                    \u002F>\n                }\n            \u002F>\n        \u003C\u002FView>\n    )\n}\n",[3829,18488,18489,18497,18532,18536,18541,18551,18557,18579,18593,18610,18618,18622,18626,18630,18635,18645,18651,18673,18695,18711,18719,18747,18755,18759,18763,18767,18772,18778,18801,18810,18827,18850,18865,18897,18905,18911,18915,18921,18933,18958,18992,18996,19006,19015,19023,19042,19055,19065,19070,19074,19078,19086,19090],{"__ignoreMap":3827},[3832,18490,18491,18493,18495],{"class":3834,"line":3835},[3832,18492,7416],{"class":3889},[3832,18494,4702],{"class":4117},[3832,18496,4705],{"class":3849},[3832,18498,18499,18501,18503,18505,18507,18509,18511,18513,18515,18518,18520,18522,18524,18526,18528,18530],{"class":3834,"line":3842},[3832,18500,4710],{"class":3889},[3832,18502,3850],{"class":3849},[3832,18504,6565],{"class":4042},[3832,18506,3857],{"class":3849},[3832,18508,4371],{"class":4042},[3832,18510,3857],{"class":3849},[3832,18512,9744],{"class":4042},[3832,18514,3857],{"class":3849},[3832,18516,18517],{"class":4042},"isError",[3832,18519,3857],{"class":3849},[3832,18521,4386],{"class":4042},[3832,18523,3857],{"class":3849},[3832,18525,18336],{"class":4042},[3832,18527,4748],{"class":3849},[3832,18529,6499],{"class":4117},[3832,18531,4230],{"class":3849},[3832,18533,18534],{"class":3834,"line":3873},[3832,18535,3877],{"emptyLinePlaceholder":3876},[3832,18537,18538],{"class":3834,"line":3880},[3832,18539,18540],{"class":3838},"    \u002F\u002F 1. ПОВНОЕКРАННИЙ ЛОАДЕР: перше завантаження (немає даних)\n",[3832,18542,18543,18545,18547,18549],{"class":3834,"line":3886},[3832,18544,4821],{"class":3845},[3832,18546,4307],{"class":3849},[3832,18548,4371],{"class":3853},[3832,18550,4189],{"class":3849},[3832,18552,18553,18555],{"class":3834,"line":3900},[3832,18554,4220],{"class":3845},[3832,18556,4914],{"class":3849},[3832,18558,18559,18561,18563,18565,18567,18569,18571,18573,18575,18577],{"class":3834,"line":3912},[3832,18560,7532],{"class":4834},[3832,18562,4630],{"class":3893},[3832,18564,8467],{"class":4840},[3832,18566,4844],{"class":3849},[3832,18568,4885],{"class":3889},[3832,18570,9970],{"class":3853},[3832,18572,4183],{"class":4947},[3832,18574,9975],{"class":3853},[3832,18576,4890],{"class":3889},[3832,18578,4898],{"class":4834},[3832,18580,18581,18583,18585,18587,18589,18591],{"class":3834,"line":3922},[3832,18582,9984],{"class":4834},[3832,18584,4645],{"class":3893},[3832,18586,4841],{"class":4840},[3832,18588,4844],{"class":3849},[3832,18590,4847],{"class":3869},[3832,18592,4850],{"class":4834},[3832,18594,18595,18597,18599,18601,18604,18606,18608],{"class":3834,"line":3932},[3832,18596,9984],{"class":4834},[3832,18598,4635],{"class":3893},[3832,18600,4879],{"class":4834},[3832,18602,18603],{"class":3849},"Завантаження поїздок...",[3832,18605,4893],{"class":4834},[3832,18607,4635],{"class":3893},[3832,18609,4898],{"class":4834},[3832,18611,18612,18614,18616],{"class":3834,"line":3942},[3832,18613,10039],{"class":4834},[3832,18615,4630],{"class":3893},[3832,18617,4898],{"class":4834},[3832,18619,18620],{"class":3834,"line":3948},[3832,18621,10048],{"class":3849},[3832,18623,18624],{"class":3834,"line":3953},[3832,18625,4236],{"class":3849},[3832,18627,18628],{"class":3834,"line":3959},[3832,18629,3877],{"emptyLinePlaceholder":3876},[3832,18631,18632],{"class":3834,"line":3969},[3832,18633,18634],{"class":3838},"    \u002F\u002F 2. ЕКРАН ПОМИЛКИ: не вдалося завантажити\n",[3832,18636,18637,18639,18641,18643],{"class":3834,"line":3986},[3832,18638,4821],{"class":3845},[3832,18640,4307],{"class":3849},[3832,18642,18517],{"class":3853},[3832,18644,4189],{"class":3849},[3832,18646,18647,18649],{"class":3834,"line":4000},[3832,18648,4220],{"class":3845},[3832,18650,4914],{"class":3849},[3832,18652,18653,18655,18657,18659,18661,18663,18665,18667,18669,18671],{"class":3834,"line":4020},[3832,18654,7532],{"class":4834},[3832,18656,4630],{"class":3893},[3832,18658,8467],{"class":4840},[3832,18660,4844],{"class":3849},[3832,18662,4885],{"class":3889},[3832,18664,9970],{"class":3853},[3832,18666,4183],{"class":4947},[3832,18668,9975],{"class":3853},[3832,18670,4890],{"class":3889},[3832,18672,4898],{"class":4834},[3832,18674,18675,18677,18679,18681,18683,18685,18687,18689,18691,18693],{"class":3834,"line":4025},[3832,18676,9984],{"class":4834},[3832,18678,4635],{"class":3893},[3832,18680,8467],{"class":4840},[3832,18682,4844],{"class":3849},[3832,18684,4885],{"class":3889},[3832,18686,9970],{"class":3853},[3832,18688,4183],{"class":4947},[3832,18690,10118],{"class":3853},[3832,18692,4890],{"class":3889},[3832,18694,4898],{"class":4834},[3832,18696,18697,18699,18701,18703,18705,18707,18709],{"class":3834,"line":4030},[3832,18698,10127],{"class":3849},[3832,18700,4885],{"class":3889},[3832,18702,4386],{"class":3853},[3832,18704,11188],{"class":4947},[3832,18706,10136],{"class":4117},[3832,18708,10139],{"class":4947},[3832,18710,3945],{"class":3889},[3832,18712,18713,18715,18717],{"class":3834,"line":4036},[3832,18714,10146],{"class":4834},[3832,18716,4635],{"class":3893},[3832,18718,4898],{"class":4834},[3832,18720,18721,18723,18726,18729,18731,18734,18737,18739,18741,18743,18745],{"class":3834,"line":4054},[3832,18722,9984],{"class":4834},[3832,18724,18725],{"class":3893},"Button",[3832,18727,18728],{"class":4840}," title",[3832,18730,4844],{"class":3849},[3832,18732,18733],{"class":3869},"\"Спробувати знову\"",[3832,18735,18736],{"class":4840}," onPress",[3832,18738,4844],{"class":3849},[3832,18740,4885],{"class":3889},[3832,18742,18336],{"class":3853},[3832,18744,4890],{"class":3889},[3832,18746,4850],{"class":4834},[3832,18748,18749,18751,18753],{"class":3834,"line":4063},[3832,18750,10039],{"class":4834},[3832,18752,4630],{"class":3893},[3832,18754,4898],{"class":4834},[3832,18756,18757],{"class":3834,"line":4075},[3832,18758,10048],{"class":3849},[3832,18760,18761],{"class":3834,"line":4086},[3832,18762,4236],{"class":3849},[3832,18764,18765],{"class":3834,"line":4091},[3832,18766,3877],{"emptyLinePlaceholder":3876},[3832,18768,18769],{"class":3834,"line":4096},[3832,18770,18771],{"class":3838},"    \u002F\u002F 3. РОБОЧИЙ СТАН: показуємо дані\n",[3832,18773,18774,18776],{"class":3834,"line":4102},[3832,18775,4911],{"class":3845},[3832,18777,4914],{"class":3849},[3832,18779,18780,18782,18784,18786,18788,18790,18792,18794,18797,18799],{"class":3834,"line":4123},[3832,18781,4919],{"class":4834},[3832,18783,4630],{"class":3893},[3832,18785,8467],{"class":4840},[3832,18787,4844],{"class":3849},[3832,18789,4885],{"class":3889},[3832,18791,9970],{"class":3853},[3832,18793,4183],{"class":4947},[3832,18795,18796],{"class":3853},"container",[3832,18798,4890],{"class":3889},[3832,18800,4898],{"class":4834},[3832,18802,18803,18805,18808],{"class":3834,"line":4131},[3832,18804,7586],{"class":3889},[3832,18806,18807],{"class":3838},"\u002F* Тонкий індикатор фонового оновлення *\u002F",[3832,18809,3945],{"class":3889},[3832,18811,18812,18814,18816,18818,18821,18823,18825],{"class":3834,"line":4145},[3832,18813,7586],{"class":3889},[3832,18815,9744],{"class":3853},[3832,18817,18261],{"class":3849},[3832,18819,18820],{"class":3849}," !",[3832,18822,4371],{"class":3853},[3832,18824,18261],{"class":3849},[3832,18826,4914],{"class":4947},[3832,18828,18829,18831,18833,18835,18837,18839,18841,18843,18846,18848],{"class":3834,"line":4171},[3832,18830,9984],{"class":4834},[3832,18832,4630],{"class":3893},[3832,18834,8467],{"class":4840},[3832,18836,4844],{"class":3849},[3832,18838,4885],{"class":3889},[3832,18840,9970],{"class":3853},[3832,18842,4183],{"class":4947},[3832,18844,18845],{"class":3853},"topBar",[3832,18847,4890],{"class":3889},[3832,18849,4898],{"class":4834},[3832,18851,18852,18854,18856,18858,18860,18863],{"class":3834,"line":4192},[3832,18853,10274],{"class":4834},[3832,18855,4645],{"class":3893},[3832,18857,4841],{"class":4840},[3832,18859,4844],{"class":3849},[3832,18861,18862],{"class":3869},"\"small\"",[3832,18864,4850],{"class":4834},[3832,18866,18867,18869,18871,18873,18875,18877,18879,18881,18884,18886,18888,18891,18893,18895],{"class":3834,"line":4211},[3832,18868,10274],{"class":4834},[3832,18870,4635],{"class":3893},[3832,18872,8467],{"class":4840},[3832,18874,4844],{"class":3849},[3832,18876,4885],{"class":3889},[3832,18878,9970],{"class":3853},[3832,18880,4183],{"class":4947},[3832,18882,18883],{"class":3853},"topBarText",[3832,18885,4890],{"class":3889},[3832,18887,4879],{"class":4834},[3832,18889,18890],{"class":4947},"Оновлення...",[3832,18892,4893],{"class":4834},[3832,18894,4635],{"class":3893},[3832,18896,4898],{"class":4834},[3832,18898,18899,18901,18903],{"class":3834,"line":4217},[3832,18900,10146],{"class":4834},[3832,18902,4630],{"class":3893},[3832,18904,4898],{"class":4834},[3832,18906,18907,18909],{"class":3834,"line":4233},[3832,18908,10360],{"class":4947},[3832,18910,3945],{"class":3889},[3832,18912,18913],{"class":3834,"line":4239},[3832,18914,8518],{"class":3849},[3832,18916,18917,18919],{"class":3834,"line":4244},[3832,18918,7532],{"class":4834},[3832,18920,4922],{"class":3893},[3832,18922,18923,18925,18927,18929,18931],{"class":3834,"line":4249},[3832,18924,17103],{"class":4840},[3832,18926,4844],{"class":3849},[3832,18928,4885],{"class":3889},[3832,18930,6565],{"class":3853},[3832,18932,3945],{"class":3889},[3832,18934,18935,18938,18940,18942,18944,18946,18948,18950,18952,18954,18956],{"class":3834,"line":4255},[3832,18936,18937],{"class":4840},"                keyExtractor",[3832,18939,4844],{"class":3849},[3832,18941,4885],{"class":3889},[3832,18943,4162],{"class":4947},[3832,18945,4950],{"class":3853},[3832,18947,4313],{"class":4947},[3832,18949,4140],{"class":3889},[3832,18951,4957],{"class":3853},[3832,18953,4183],{"class":4947},[3832,18955,4962],{"class":3853},[3832,18957,3945],{"class":3889},[3832,18959,18960,18962,18964,18966,18968,18970,18972,18974,18976,18978,18980,18982,18984,18986,18988,18990],{"class":3834,"line":4270},[3832,18961,17116],{"class":4840},[3832,18963,4844],{"class":3849},[3832,18965,4885],{"class":3889},[3832,18967,4976],{"class":4947},[3832,18969,4950],{"class":3853},[3832,18971,4981],{"class":4947},[3832,18973,4140],{"class":3889},[3832,18975,4835],{"class":4834},[3832,18977,17133],{"class":3893},[3832,18979,17136],{"class":4840},[3832,18981,4844],{"class":3849},[3832,18983,4885],{"class":3889},[3832,18985,4950],{"class":3853},[3832,18987,4890],{"class":3889},[3832,18989,17147],{"class":4834},[3832,18991,3945],{"class":3889},[3832,18993,18994],{"class":3834,"line":4281},[3832,18995,14921],{"class":3849},[3832,18997,18998,19001,19004],{"class":3834,"line":4289},[3832,18999,19000],{"class":3889},"                {",[3832,19002,19003],{"class":3838},"\u002F* Pull-to-Refresh *\u002F",[3832,19005,3945],{"class":3889},[3832,19007,19008,19011,19013],{"class":3834,"line":4298},[3832,19009,19010],{"class":4840},"                refreshControl",[3832,19012,4844],{"class":3849},[3832,19014,11782],{"class":3889},[3832,19016,19017,19019,19021],{"class":3834,"line":4320},[3832,19018,10274],{"class":4834},[3832,19020,18431],{"class":3893},[3832,19022,7538],{"class":4947},[3832,19024,19025,19028,19030,19032,19034,19036,19038,19040],{"class":3834,"line":4326},[3832,19026,19027],{"class":4840},"                        refreshing",[3832,19029,4844],{"class":3849},[3832,19031,4885],{"class":3889},[3832,19033,9744],{"class":3853},[3832,19035,18261],{"class":3849},[3832,19037,18820],{"class":3849},[3832,19039,4371],{"class":3853},[3832,19041,3945],{"class":3889},[3832,19043,19044,19047,19049,19051,19053],{"class":3834,"line":4332},[3832,19045,19046],{"class":4840},"                        onRefresh",[3832,19048,4844],{"class":3849},[3832,19050,4885],{"class":3889},[3832,19052,18336],{"class":3853},[3832,19054,3945],{"class":3889},[3832,19056,19057,19060,19062],{"class":3834,"line":4363},[3832,19058,19059],{"class":4840},"                        tintColor",[3832,19061,4844],{"class":3849},[3832,19063,19064],{"class":3869},"\"#3b82f6\"\n",[3832,19066,19067],{"class":3834,"line":4379},[3832,19068,19069],{"class":4834},"                    \u002F>\n",[3832,19071,19072],{"class":3834,"line":4394},[3832,19073,15165],{"class":3889},[3832,19075,19076],{"class":3834,"line":4400},[3832,19077,7581],{"class":4834},[3832,19079,19080,19082,19084],{"class":3834,"line":4406},[3832,19081,7596],{"class":4834},[3832,19083,4630],{"class":3893},[3832,19085,4898],{"class":4834},[3832,19087,19088],{"class":3834,"line":4437},[3832,19089,5018],{"class":3849},[3832,19091,19092],{"class":3834,"line":4451},[3832,19093,3945],{"class":3849},[3809,19095,19097],{"id":19096},"рівень-5-lazy-queries-запити-на-вимогу","Рівень 5: Lazy Queries (запити на вимогу)",[3801,19099,19100],{},"Іноді потрібно запустити запит НЕ автоматично при монтуванні, а у відповідь на дію користувача (наприклад, натискання кнопки):",[3822,19102,19104],{"className":3824,"code":19103,"language":3826,"meta":3827,"style":3827},"export const { useGetTripByIdQuery, useLazyGetTripByIdQuery } = tripsApi\n",[3829,19105,19106],{"__ignoreMap":3827},[3832,19107,19108,19110,19112,19114,19116,19118,19121,19123],{"class":3834,"line":3835},[3832,19109,4105],{"class":3845},[3832,19111,4108],{"class":3889},[3832,19113,3850],{"class":3849},[3832,19115,8328],{"class":4042},[3832,19117,3857],{"class":3849},[3832,19119,19120],{"class":4042},"useLazyGetTripByIdQuery",[3832,19122,4748],{"class":3849},[3832,19124,6509],{"class":3853},[3801,19126,19127],{},[3770,19128,19129],{},"Різниця між звичайним та lazy хуком:",[6860,19131,19132,19208],{},[3822,19133,19136],{"className":4592,"code":19134,"filename":19135,"language":4594,"meta":3827,"style":3827},"function TripScreen({ tripId }) {\n    \u002F\u002F Запит виконується ОДРАЗУ при рендері\n    const { data } = useGetTripByIdQuery(tripId)\n    \n    return \u003CText>{data?.title}\u003C\u002FText>\n}\n","useGetTripByIdQuery (авто)",[3829,19137,19138,19151,19156,19174,19178,19204],{"__ignoreMap":3827},[3832,19139,19140,19142,19145,19147,19149],{"class":3834,"line":3835},[3832,19141,7416],{"class":3889},[3832,19143,19144],{"class":4117}," TripScreen",[3832,19146,4976],{"class":3849},[3832,19148,8350],{"class":3853},[3832,19150,8353],{"class":3849},[3832,19152,19153],{"class":3834,"line":3842},[3832,19154,19155],{"class":3838},"    \u002F\u002F Запит виконується ОДРАЗУ при рендері\n",[3832,19157,19158,19160,19162,19164,19166,19168,19170,19172],{"class":3834,"line":3873},[3832,19159,4710],{"class":3889},[3832,19161,3850],{"class":3849},[3832,19163,6565],{"class":4042},[3832,19165,4748],{"class":3849},[3832,19167,8328],{"class":4117},[3832,19169,4162],{"class":3849},[3832,19171,8350],{"class":3853},[3832,19173,4168],{"class":3849},[3832,19175,19176],{"class":3834,"line":3880},[3832,19177,4724],{"class":3849},[3832,19179,19180,19182,19184,19186,19188,19190,19192,19194,19196,19198,19200,19202],{"class":3834,"line":3886},[3832,19181,4911],{"class":3845},[3832,19183,4835],{"class":4834},[3832,19185,4635],{"class":3893},[3832,19187,4879],{"class":4834},[3832,19189,4885],{"class":3889},[3832,19191,6565],{"class":3853},[3832,19193,11188],{"class":4947},[3832,19195,4998],{"class":3853},[3832,19197,4890],{"class":3889},[3832,19199,4893],{"class":4834},[3832,19201,4635],{"class":3893},[3832,19203,4898],{"class":4834},[3832,19205,19206],{"class":3834,"line":3900},[3832,19207,3945],{"class":3849},[3822,19209,19212],{"className":4592,"code":19210,"filename":19211,"language":4594,"meta":3827,"style":3827},"function SearchScreen() {\n    const [tripId, setTripId] = useState('')\n    \n    \u002F\u002F Запит НЕ виконується автоматично\n    \u002F\u002F Повертає [тригер-функцію, результат]\n    const [fetchTrip, { data, isLoading }] = useLazyGetTripByIdQuery()\n    \n    const handleSearch = () => {\n        \u002F\u002F Запит виконається тільки тут!\n        fetchTrip(tripId)\n    }\n    \n    return (\n        \u003CView>\n            \u003CTextInput \n                value={tripId} \n                onChangeText={setTripId}\n                placeholder=\"Введіть ID поїздки\"\n            \u002F>\n            \u003CButton title=\"Знайти\" onPress={handleSearch} \u002F>\n            \n            {isLoading && \u003CActivityIndicator \u002F>}\n            {data && \u003CText>{data.title}\u003C\u002FText>}\n        \u003C\u002FView>\n    )\n}\n","useLazyGetTripByIdQuery (ручний)",[3829,19213,19214,19223,19246,19250,19255,19260,19284,19288,19302,19307,19318,19322,19326,19332,19340,19348,19362,19374,19383,19387,19413,19417,19433,19465,19473,19477],{"__ignoreMap":3827},[3832,19215,19216,19218,19221],{"class":3834,"line":3835},[3832,19217,7416],{"class":3889},[3832,19219,19220],{"class":4117}," SearchScreen",[3832,19222,4705],{"class":3849},[3832,19224,19225,19227,19229,19231,19233,19236,19238,19240,19242,19244],{"class":3834,"line":3842},[3832,19226,4710],{"class":3889},[3832,19228,6274],{"class":3849},[3832,19230,8350],{"class":4042},[3832,19232,3857],{"class":3849},[3832,19234,19235],{"class":4042},"setTripId",[3832,19237,7437],{"class":3849},[3832,19239,7440],{"class":4117},[3832,19241,4162],{"class":3849},[3832,19243,7445],{"class":3869},[3832,19245,4168],{"class":3849},[3832,19247,19248],{"class":3834,"line":3873},[3832,19249,4724],{"class":3849},[3832,19251,19252],{"class":3834,"line":3880},[3832,19253,19254],{"class":3838},"    \u002F\u002F Запит НЕ виконується автоматично\n",[3832,19256,19257],{"class":3834,"line":3886},[3832,19258,19259],{"class":3838},"    \u002F\u002F Повертає [тригер-функцію, результат]\n",[3832,19261,19262,19264,19266,19269,19271,19273,19275,19277,19280,19282],{"class":3834,"line":3900},[3832,19263,4710],{"class":3889},[3832,19265,6274],{"class":3849},[3832,19267,19268],{"class":4042},"fetchTrip",[3832,19270,4611],{"class":3849},[3832,19272,6565],{"class":4042},[3832,19274,3857],{"class":3849},[3832,19276,4371],{"class":4042},[3832,19278,19279],{"class":3849}," }] = ",[3832,19281,19120],{"class":4117},[3832,19283,4230],{"class":3849},[3832,19285,19286],{"class":3834,"line":3912},[3832,19287,4724],{"class":3849},[3832,19289,19290,19292,19295,19298,19300],{"class":3834,"line":3922},[3832,19291,4710],{"class":3889},[3832,19293,19294],{"class":4117}," handleSearch",[3832,19296,19297],{"class":3849}," = () ",[3832,19299,4140],{"class":3889},[3832,19301,3897],{"class":3849},[3832,19303,19304],{"class":3834,"line":3932},[3832,19305,19306],{"class":3838},"        \u002F\u002F Запит виконається тільки тут!\n",[3832,19308,19309,19312,19314,19316],{"class":3834,"line":3942},[3832,19310,19311],{"class":4117},"        fetchTrip",[3832,19313,4162],{"class":3849},[3832,19315,8350],{"class":3853},[3832,19317,4168],{"class":3849},[3832,19319,19320],{"class":3834,"line":3948},[3832,19321,4236],{"class":3849},[3832,19323,19324],{"class":3834,"line":3953},[3832,19325,4724],{"class":3849},[3832,19327,19328,19330],{"class":3834,"line":3959},[3832,19329,4911],{"class":3845},[3832,19331,4914],{"class":3849},[3832,19333,19334,19336,19338],{"class":3834,"line":3969},[3832,19335,4919],{"class":4834},[3832,19337,4630],{"class":3893},[3832,19339,4898],{"class":4834},[3832,19341,19342,19344,19346],{"class":3834,"line":3986},[3832,19343,7532],{"class":4834},[3832,19345,7535],{"class":3893},[3832,19347,7538],{"class":3849},[3832,19349,19350,19352,19354,19356,19358,19360],{"class":3834,"line":4000},[3832,19351,7543],{"class":4840},[3832,19353,4844],{"class":3849},[3832,19355,4885],{"class":3889},[3832,19357,8350],{"class":3853},[3832,19359,4890],{"class":3889},[3832,19361,7538],{"class":3849},[3832,19363,19364,19366,19368,19370,19372],{"class":3834,"line":4020},[3832,19365,7558],{"class":4840},[3832,19367,4844],{"class":3849},[3832,19369,4885],{"class":3889},[3832,19371,19235],{"class":3853},[3832,19373,3945],{"class":3889},[3832,19375,19376,19378,19380],{"class":3834,"line":4025},[3832,19377,7571],{"class":4840},[3832,19379,4844],{"class":3849},[3832,19381,19382],{"class":3869},"\"Введіть ID поїздки\"\n",[3832,19384,19385],{"class":3834,"line":4030},[3832,19386,7581],{"class":4834},[3832,19388,19389,19391,19393,19395,19397,19400,19402,19404,19406,19409,19411],{"class":3834,"line":4036},[3832,19390,7532],{"class":4834},[3832,19392,18725],{"class":3893},[3832,19394,18728],{"class":4840},[3832,19396,4844],{"class":3849},[3832,19398,19399],{"class":3869},"\"Знайти\"",[3832,19401,18736],{"class":4840},[3832,19403,4844],{"class":3849},[3832,19405,4885],{"class":3889},[3832,19407,19408],{"class":3853},"handleSearch",[3832,19410,4890],{"class":3889},[3832,19412,4850],{"class":4834},[3832,19414,19415],{"class":3834,"line":4054},[3832,19416,8518],{"class":3849},[3832,19418,19419,19421,19423,19425,19427,19429,19431],{"class":3834,"line":4063},[3832,19420,7586],{"class":3889},[3832,19422,4371],{"class":3853},[3832,19424,18261],{"class":3849},[3832,19426,4835],{"class":4834},[3832,19428,4645],{"class":3893},[3832,19430,17147],{"class":4834},[3832,19432,3945],{"class":3889},[3832,19434,19435,19437,19439,19441,19443,19445,19447,19449,19451,19453,19455,19457,19459,19461,19463],{"class":3834,"line":4075},[3832,19436,7586],{"class":3889},[3832,19438,6565],{"class":3853},[3832,19440,18261],{"class":3849},[3832,19442,4835],{"class":4834},[3832,19444,4635],{"class":3893},[3832,19446,4879],{"class":4834},[3832,19448,4885],{"class":3889},[3832,19450,6565],{"class":3853},[3832,19452,4183],{"class":4947},[3832,19454,4998],{"class":3853},[3832,19456,4890],{"class":3889},[3832,19458,4893],{"class":4834},[3832,19460,4635],{"class":3893},[3832,19462,4879],{"class":4834},[3832,19464,3945],{"class":3889},[3832,19466,19467,19469,19471],{"class":3834,"line":4086},[3832,19468,7596],{"class":4834},[3832,19470,4630],{"class":3893},[3832,19472,4898],{"class":4834},[3832,19474,19475],{"class":3834,"line":4091},[3832,19476,5018],{"class":3849},[3832,19478,19479],{"class":3834,"line":4096},[3832,19480,3945],{"class":3849},[3801,19482,19483],{},[3770,19484,19485],{},"Типові випадки використання Lazy Queries:",[3746,19487,19488,19491,19494,19497],{},[3749,19489,19490],{},"🔍 Пошук за введенням користувача",[3749,19492,19493],{},"📤 Завантаження додаткових даних при натисканні \"Показати більше\"",[3749,19495,19496],{},"🎯 Запити, які залежать від результату попереднього запиту",[3749,19498,19499],{},"🔐 Перевірка даних при submit форми",[3809,19501,19503,19504],{"id":19502},"рівень-6-оптимізація-рендерів-через-selectfromresult","Рівень 6: Оптимізація рендерів через ",[3829,19505,19506],{},"selectFromResult",[3801,19508,19509],{},"За замовчуванням компонент ререндериться при будь-якій зміні у відповіді. Але іноді потрібна лише частина даних:",[3822,19511,19513],{"className":4592,"code":19512,"language":4594,"meta":3827,"style":3827},"\u002F\u002F ❌ ПРОБЛЕМА: Компонент ререндериться при зміні БУДЬ-ЯКОЇ поїздки у списку\nfunction TripTitle({ tripId }) {\n    const { data: trips } = useGetTripsQuery()\n    const trip = trips?.find(t => t.id === tripId)\n    \n    return \u003CText>{trip?.title}\u003C\u002FText>\n}\n",[3829,19514,19515,19520,19533,19551,19586,19590,19616],{"__ignoreMap":3827},[3832,19516,19517],{"class":3834,"line":3835},[3832,19518,19519],{"class":3838},"\u002F\u002F ❌ ПРОБЛЕМА: Компонент ререндериться при зміні БУДЬ-ЯКОЇ поїздки у списку\n",[3832,19521,19522,19524,19527,19529,19531],{"class":3834,"line":3842},[3832,19523,7416],{"class":3889},[3832,19525,19526],{"class":4117}," TripTitle",[3832,19528,4976],{"class":3849},[3832,19530,8350],{"class":3853},[3832,19532,8353],{"class":3849},[3832,19534,19535,19537,19539,19541,19543,19545,19547,19549],{"class":3834,"line":3873},[3832,19536,4710],{"class":3889},[3832,19538,3850],{"class":3849},[3832,19540,6565],{"class":3853},[3832,19542,3906],{"class":3849},[3832,19544,4458],{"class":4042},[3832,19546,4748],{"class":3849},[3832,19548,6499],{"class":4117},[3832,19550,4230],{"class":3849},[3832,19552,19553,19555,19557,19559,19561,19563,19566,19568,19571,19573,19576,19578,19580,19582,19584],{"class":3834,"line":3880},[3832,19554,4710],{"class":3889},[3832,19556,17136],{"class":4042},[3832,19558,4114],{"class":3849},[3832,19560,4458],{"class":3853},[3832,19562,11188],{"class":3849},[3832,19564,19565],{"class":4117},"find",[3832,19567,4162],{"class":3849},[3832,19569,19570],{"class":3853},"t",[3832,19572,11121],{"class":3889},[3832,19574,19575],{"class":3853}," t",[3832,19577,4183],{"class":3849},[3832,19579,4962],{"class":3853},[3832,19581,5921],{"class":3849},[3832,19583,8350],{"class":3853},[3832,19585,4168],{"class":3849},[3832,19587,19588],{"class":3834,"line":3886},[3832,19589,4724],{"class":3849},[3832,19591,19592,19594,19596,19598,19600,19602,19604,19606,19608,19610,19612,19614],{"class":3834,"line":3900},[3832,19593,4911],{"class":3845},[3832,19595,4835],{"class":4834},[3832,19597,4635],{"class":3893},[3832,19599,4879],{"class":4834},[3832,19601,4885],{"class":3889},[3832,19603,8412],{"class":3853},[3832,19605,11188],{"class":4947},[3832,19607,4998],{"class":3853},[3832,19609,4890],{"class":3889},[3832,19611,4893],{"class":4834},[3832,19613,4635],{"class":3893},[3832,19615,4898],{"class":4834},[3832,19617,19618],{"class":3834,"line":3912},[3832,19619,3945],{"class":3849},[3801,19621,19622],{},[3770,19623,19624],{},"Рішення:",[3822,19626,19628],{"className":4592,"code":19627,"language":4594,"meta":3827,"style":3827},"\u002F\u002F ✅ ОПТИМІЗАЦІЯ: Ререндер тільки при зміні цієї конкретної поїздки\nfunction TripTitle({ tripId }) {\n    const { trip } = useGetTripsQuery(undefined, {\n        \u002F\u002F selectFromResult дозволяє підписатись лише на частину даних\n        selectFromResult: ({ data }) => ({\n            trip: data?.find(t => t.id === tripId),\n        }),\n    })\n    \n    return \u003CText>{trip?.title}\u003C\u002FText>\n}\n",[3829,19629,19630,19635,19647,19665,19670,19688,19717,19721,19725,19729,19755],{"__ignoreMap":3827},[3832,19631,19632],{"class":3834,"line":3835},[3832,19633,19634],{"class":3838},"\u002F\u002F ✅ ОПТИМІЗАЦІЯ: Ререндер тільки при зміні цієї конкретної поїздки\n",[3832,19636,19637,19639,19641,19643,19645],{"class":3834,"line":3842},[3832,19638,7416],{"class":3889},[3832,19640,19526],{"class":4117},[3832,19642,4976],{"class":3849},[3832,19644,8350],{"class":3853},[3832,19646,8353],{"class":3849},[3832,19648,19649,19651,19653,19655,19657,19659,19661,19663],{"class":3834,"line":3873},[3832,19650,4710],{"class":3889},[3832,19652,3850],{"class":3849},[3832,19654,8412],{"class":4042},[3832,19656,4748],{"class":3849},[3832,19658,6499],{"class":4117},[3832,19660,4162],{"class":3849},[3832,19662,16886],{"class":3889},[3832,19664,5117],{"class":3849},[3832,19666,19667],{"class":3834,"line":3880},[3832,19668,19669],{"class":3838},"        \u002F\u002F selectFromResult дозволяє підписатись лише на частину даних\n",[3832,19671,19672,19675,19677,19680,19682,19684,19686],{"class":3834,"line":3886},[3832,19673,19674],{"class":4117},"        selectFromResult",[3832,19676,4304],{"class":3853},[3832,19678,19679],{"class":3849}," ({ ",[3832,19681,6565],{"class":3853},[3832,19683,4981],{"class":3849},[3832,19685,4140],{"class":3889},[3832,19687,6301],{"class":3849},[3832,19689,19690,19693,19695,19697,19699,19701,19703,19705,19707,19709,19711,19713,19715],{"class":3834,"line":3900},[3832,19691,19692],{"class":3853},"            trip:",[3832,19694,18279],{"class":3853},[3832,19696,11188],{"class":3849},[3832,19698,19565],{"class":4117},[3832,19700,4162],{"class":3849},[3832,19702,19570],{"class":3853},[3832,19704,11121],{"class":3889},[3832,19706,19575],{"class":3853},[3832,19708,4183],{"class":3849},[3832,19710,4962],{"class":3853},[3832,19712,5921],{"class":3849},[3832,19714,8350],{"class":3853},[3832,19716,5165],{"class":3849},[3832,19718,19719],{"class":3834,"line":3912},[3832,19720,6367],{"class":3849},[3832,19722,19723],{"class":3834,"line":3922},[3832,19724,5951],{"class":3849},[3832,19726,19727],{"class":3834,"line":3932},[3832,19728,4724],{"class":3849},[3832,19730,19731,19733,19735,19737,19739,19741,19743,19745,19747,19749,19751,19753],{"class":3834,"line":3942},[3832,19732,4911],{"class":3845},[3832,19734,4835],{"class":4834},[3832,19736,4635],{"class":3893},[3832,19738,4879],{"class":4834},[3832,19740,4885],{"class":3889},[3832,19742,8412],{"class":3853},[3832,19744,11188],{"class":4947},[3832,19746,4998],{"class":3853},[3832,19748,4890],{"class":3889},[3832,19750,4893],{"class":4834},[3832,19752,4635],{"class":3893},[3832,19754,4898],{"class":4834},[3832,19756,19757],{"class":3834,"line":3948},[3832,19758,3945],{"class":3849},[3801,19760,19761,19762,19765,19766,19768],{},"Тепер компонент оновиться ",[3770,19763,19764],{},"тільки"," якщо змінилась поїздка з ID=",[3829,19767,8350],{},", а не при зміні будь-якої іншої поїздки!",[8569,19770,19771,19774,19775,19777],{},[3770,19772,19773],{},"Рекомендація:"," Використовуйте ",[3829,19776,19506],{}," для великих списків або коли один запит використовується багатьма компонентами з різними потребами у даних.",[3793,19779],{},[3796,19781,19783],{"id":19782},"зміна-даних-mutation-endpoints","Зміна даних: Mutation Endpoints",[3801,19785,19786,19787,19790,19791,19794,19795,19798],{},"Тепер, коли ми навчилися ",[3770,19788,19789],{},"читати"," дані через Query, час навчитися їх ",[3770,19792,19793],{},"змінювати",". Mutations (",[3817,19796,19797],{},"мутації",") — це операції, які модифікують дані на сервері: створення, оновлення, видалення.",[3809,19800,19802],{"id":19801},"ключова-різниця-між-query-та-mutation","Ключова різниця між Query та Mutation",[6860,19804,19805,19840],{},[3822,19806,19809],{"className":3824,"code":19807,"filename":19808,"language":3826,"meta":3827,"style":3827},"\u002F\u002F ✅ Виконується АВТОМАТИЧНО при монтуванні\n\u002F\u002F ✅ Результат кешується\n\u002F\u002F ✅ Можна викликати багато разів без побічних ефектів\nconst { data } = useGetTripsQuery()\n","Query (читання)",[3829,19810,19811,19816,19821,19826],{"__ignoreMap":3827},[3832,19812,19813],{"class":3834,"line":3835},[3832,19814,19815],{"class":3838},"\u002F\u002F ✅ Виконується АВТОМАТИЧНО при монтуванні\n",[3832,19817,19818],{"class":3834,"line":3842},[3832,19819,19820],{"class":3838},"\u002F\u002F ✅ Результат кешується\n",[3832,19822,19823],{"class":3834,"line":3873},[3832,19824,19825],{"class":3838},"\u002F\u002F ✅ Можна викликати багато разів без побічних ефектів\n",[3832,19827,19828,19830,19832,19834,19836,19838],{"class":3834,"line":3880},[3832,19829,4039],{"class":3889},[3832,19831,3850],{"class":3849},[3832,19833,6565],{"class":4042},[3832,19835,4748],{"class":3849},[3832,19837,6499],{"class":4117},[3832,19839,4230],{"class":3849},[3822,19841,19844],{"className":3824,"code":19842,"filename":19843,"language":3826,"meta":3827,"style":3827},"\u002F\u002F ❌ НЕ виконується автоматично\n\u002F\u002F ❌ Результат НЕ кешується (немає сенсу)\n\u002F\u002F ⚠️ Кожен виклик змінює дані на сервері!\nconst [createTrip, { isLoading }] = useCreateTripMutation()\n","Mutation (зміна)",[3829,19845,19846,19851,19856,19861],{"__ignoreMap":3827},[3832,19847,19848],{"class":3834,"line":3835},[3832,19849,19850],{"class":3838},"\u002F\u002F ❌ НЕ виконується автоматично\n",[3832,19852,19853],{"class":3834,"line":3842},[3832,19854,19855],{"class":3838},"\u002F\u002F ❌ Результат НЕ кешується (немає сенсу)\n",[3832,19857,19858],{"class":3834,"line":3873},[3832,19859,19860],{"class":3838},"\u002F\u002F ⚠️ Кожен виклик змінює дані на сервері!\n",[3832,19862,19863,19865,19867,19869,19871,19873,19875,19877],{"class":3834,"line":3880},[3832,19864,4039],{"class":3889},[3832,19866,6274],{"class":3849},[3832,19868,5238],{"class":4042},[3832,19870,4611],{"class":3849},[3832,19872,4371],{"class":4042},[3832,19874,19279],{"class":3849},[3832,19876,6504],{"class":4117},[3832,19878,4230],{"class":3849},[3801,19880,19881],{},[3770,19882,19883],{},"Чому мутації не кешуються?",[3801,19885,19886,19887,19890,19891,4307,19894,19897],{},"Уявіть, що ви натискаєте \"Створити поїздку\" двічі — має створитись ",[3770,19888,19889],{},"дві"," різні поїздки, а не повернутись результат першого запиту. Мутації мають ",[3770,19892,19893],{},"побічні ефекти",[3817,19895,19896],{},"side effects",") — вони змінюють стан сервера.",[3809,19899,19901],{"id":19900},"рівень-1-найпростіша-мутація-post","Рівень 1: Найпростіша мутація (POST)",[3801,19903,19904],{},"Почнемо з створення нової поїздки:",[3822,19906,19908],{"className":3824,"code":19907,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fservices\u002FtripsApi.ts\ninterface Trip {\n    id: string\n    title: string\n    region: string\n    startDate: string\n}\n\n\u002F\u002F Дані для створення (без ID — його поверне сервер)\ninterface CreateTripDto {\n    title: string\n    region: string\n    startDate: string\n}\n\nexport const tripsApi = createApi({\n    baseQuery: fetchBaseQuery({ baseUrl: 'http:\u002F\u002Flocalhost:3000' }),\n    tagTypes: ['Trip'],\n    endpoints: (builder) => ({\n        \u002F\u002F Query для читання\n        getTrips: builder.query\u003CTrip[], void>({\n            query: () => '\u002Ftrips',\n            providesTags: ['Trip'],\n        }),\n        \n        \u002F\u002F Mutation для створення\n        createTrip: builder.mutation\u003CTrip, CreateTripDto>({\n            query: (newTrip) => ({\n                url: '\u002Ftrips',\n                method: 'POST',\n                body: newTrip,\n            }),\n            invalidatesTags: ['Trip'],  \u002F\u002F Оновити список після створення\n        }),\n    }),\n})\n\nexport const { useGetTripsQuery, useCreateTripMutation } = tripsApi\n",[3829,19909,19910,19914,19922,19930,19938,19946,19954,19958,19962,19967,19976,19984,19992,20000,20004,20008,20022,20036,20046,20062,20067,20087,20101,20111,20115,20119,20124,20145,20161,20169,20177,20185,20189,20202,20206,20210,20214,20218],{"__ignoreMap":3827},[3832,19911,19912],{"class":3834,"line":3835},[3832,19913,11022],{"class":3838},[3832,19915,19916,19918,19920],{"class":3834,"line":3842},[3832,19917,3890],{"class":3889},[3832,19919,3894],{"class":3893},[3832,19921,3897],{"class":3849},[3832,19923,19924,19926,19928],{"class":3834,"line":3873},[3832,19925,3903],{"class":3853},[3832,19927,3906],{"class":3849},[3832,19929,3909],{"class":3893},[3832,19931,19932,19934,19936],{"class":3834,"line":3880},[3832,19933,3915],{"class":3853},[3832,19935,3906],{"class":3849},[3832,19937,3909],{"class":3893},[3832,19939,19940,19942,19944],{"class":3834,"line":3886},[3832,19941,3925],{"class":3853},[3832,19943,3906],{"class":3849},[3832,19945,3909],{"class":3893},[3832,19947,19948,19950,19952],{"class":3834,"line":3900},[3832,19949,3935],{"class":3853},[3832,19951,3906],{"class":3849},[3832,19953,3909],{"class":3893},[3832,19955,19956],{"class":3834,"line":3912},[3832,19957,3945],{"class":3849},[3832,19959,19960],{"class":3834,"line":3922},[3832,19961,3877],{"emptyLinePlaceholder":3876},[3832,19963,19964],{"class":3834,"line":3932},[3832,19965,19966],{"class":3838},"\u002F\u002F Дані для створення (без ID — його поверне сервер)\n",[3832,19968,19969,19971,19974],{"class":3834,"line":3942},[3832,19970,3890],{"class":3889},[3832,19972,19973],{"class":3893}," CreateTripDto",[3832,19975,3897],{"class":3849},[3832,19977,19978,19980,19982],{"class":3834,"line":3948},[3832,19979,3915],{"class":3853},[3832,19981,3906],{"class":3849},[3832,19983,3909],{"class":3893},[3832,19985,19986,19988,19990],{"class":3834,"line":3953},[3832,19987,3925],{"class":3853},[3832,19989,3906],{"class":3849},[3832,19991,3909],{"class":3893},[3832,19993,19994,19996,19998],{"class":3834,"line":3959},[3832,19995,3935],{"class":3853},[3832,19997,3906],{"class":3849},[3832,19999,3909],{"class":3893},[3832,20001,20002],{"class":3834,"line":3969},[3832,20003,3945],{"class":3849},[3832,20005,20006],{"class":3834,"line":3986},[3832,20007,3877],{"emptyLinePlaceholder":3876},[3832,20009,20010,20012,20014,20016,20018,20020],{"class":3834,"line":4000},[3832,20011,4105],{"class":3845},[3832,20013,4108],{"class":3889},[3832,20015,6231],{"class":4042},[3832,20017,4114],{"class":3849},[3832,20019,6153],{"class":4117},[3832,20021,4267],{"class":3849},[3832,20023,20024,20026,20028,20030,20032,20034],{"class":3834,"line":4020},[3832,20025,6252],{"class":3853},[3832,20027,6255],{"class":4117},[3832,20029,4976],{"class":3849},[3832,20031,6260],{"class":3853},[3832,20033,6263],{"class":3869},[3832,20035,6266],{"class":3849},[3832,20037,20038,20040,20042,20044],{"class":3834,"line":4025},[3832,20039,6271],{"class":3853},[3832,20041,6274],{"class":3849},[3832,20043,6277],{"class":3869},[3832,20045,11605],{"class":3849},[3832,20047,20048,20050,20052,20054,20056,20058,20060],{"class":3834,"line":4030},[3832,20049,6288],{"class":4117},[3832,20051,4304],{"class":3853},[3832,20053,4307],{"class":3849},[3832,20055,4310],{"class":3853},[3832,20057,4313],{"class":3849},[3832,20059,4140],{"class":3889},[3832,20061,6301],{"class":3849},[3832,20063,20064],{"class":3834,"line":4036},[3832,20065,20066],{"class":3838},"        \u002F\u002F Query для читання\n",[3832,20068,20069,20071,20073,20075,20077,20079,20081,20083,20085],{"class":3834,"line":4054},[3832,20070,6311],{"class":3853},[3832,20072,6314],{"class":3853},[3832,20074,4183],{"class":3849},[3832,20076,6319],{"class":4117},[3832,20078,5084],{"class":3849},[3832,20080,3977],{"class":3893},[3832,20082,6326],{"class":3849},[3832,20084,6329],{"class":3893},[3832,20086,6332],{"class":3849},[3832,20088,20089,20091,20093,20095,20097,20099],{"class":3834,"line":4063},[3832,20090,6337],{"class":4117},[3832,20092,4304],{"class":3853},[3832,20094,4137],{"class":3849},[3832,20096,4140],{"class":3889},[3832,20098,6346],{"class":3869},[3832,20100,4072],{"class":3849},[3832,20102,20103,20105,20107,20109],{"class":3834,"line":4075},[3832,20104,6353],{"class":3853},[3832,20106,6274],{"class":3849},[3832,20108,6277],{"class":3869},[3832,20110,11605],{"class":3849},[3832,20112,20113],{"class":3834,"line":4086},[3832,20114,6367],{"class":3849},[3832,20116,20117],{"class":3834,"line":4091},[3832,20118,11390],{"class":3849},[3832,20120,20121],{"class":3834,"line":4096},[3832,20122,20123],{"class":3838},"        \u002F\u002F Mutation для створення\n",[3832,20125,20126,20128,20130,20132,20134,20136,20138,20140,20143],{"class":3834,"line":4102},[3832,20127,6377],{"class":3853},[3832,20129,6314],{"class":3853},[3832,20131,4183],{"class":3849},[3832,20133,6384],{"class":4117},[3832,20135,5084],{"class":3849},[3832,20137,3977],{"class":3893},[3832,20139,3857],{"class":3849},[3832,20141,20142],{"class":3893},"CreateTripDto",[3832,20144,6332],{"class":3849},[3832,20146,20147,20149,20151,20153,20155,20157,20159],{"class":3834,"line":4123},[3832,20148,6337],{"class":4117},[3832,20150,4304],{"class":3853},[3832,20152,4307],{"class":3849},[3832,20154,5076],{"class":3853},[3832,20156,4313],{"class":3849},[3832,20158,4140],{"class":3889},[3832,20160,6301],{"class":3849},[3832,20162,20163,20165,20167],{"class":3834,"line":4131},[3832,20164,6424],{"class":3853},[3832,20166,6346],{"class":3869},[3832,20168,4072],{"class":3849},[3832,20170,20171,20173,20175],{"class":3834,"line":4145},[3832,20172,6433],{"class":3853},[3832,20174,5125],{"class":3869},[3832,20176,4072],{"class":3849},[3832,20178,20179,20181,20183],{"class":3834,"line":4171},[3832,20180,6442],{"class":3853},[3832,20182,6445],{"class":3853},[3832,20184,4072],{"class":3849},[3832,20186,20187],{"class":3834,"line":4192},[3832,20188,6452],{"class":3849},[3832,20190,20191,20193,20195,20197,20199],{"class":3834,"line":4211},[3832,20192,6457],{"class":3853},[3832,20194,6274],{"class":3849},[3832,20196,6277],{"class":3869},[3832,20198,6280],{"class":3849},[3832,20200,20201],{"class":3838},"\u002F\u002F Оновити список після створення\n",[3832,20203,20204],{"class":3834,"line":4217},[3832,20205,6367],{"class":3849},[3832,20207,20208],{"class":3834,"line":4233},[3832,20209,6475],{"class":3849},[3832,20211,20212],{"class":3834,"line":4239},[3832,20213,4566],{"class":3849},[3832,20215,20216],{"class":3834,"line":4244},[3832,20217,3877],{"emptyLinePlaceholder":3876},[3832,20219,20220,20222,20224,20226,20228,20230,20232,20234],{"class":3834,"line":4249},[3832,20221,4105],{"class":3845},[3832,20223,4108],{"class":3889},[3832,20225,3850],{"class":3849},[3832,20227,6499],{"class":4042},[3832,20229,3857],{"class":3849},[3832,20231,6504],{"class":4042},[3832,20233,4748],{"class":3849},[3832,20235,6509],{"class":3853},[3801,20237,20238],{},[3770,20239,15715],{},[3822,20241,20243],{"className":4592,"code":20242,"language":4594,"meta":3827,"style":3827},"\u002F\u002F app\u002Fscreens\u002FCreateTripScreen.tsx\nimport { useState } from 'react'\nimport { View, TextInput, Button, Text, ActivityIndicator } from 'react-native'\nimport { useCreateTripMutation } from '@\u002Fservices\u002FtripsApi'\nimport { useRouter } from 'expo-router'\n\nexport function CreateTripScreen() {\n    const router = useRouter()\n    \n    \u002F\u002F Хук мутації повертає [функцію-тригер, стан запиту]\n    const [createTrip, { isLoading, error, isSuccess }] = useCreateTripMutation()\n    \n    const [title, setTitle] = useState('')\n    const [region, setRegion] = useState('')\n    \n    const handleSubmit = async () => {\n        try {\n            \u002F\u002F Викликаємо мутацію вручну\n            const result = await createTrip({\n                title,\n                region,\n                startDate: new Date().toISOString(),\n            }).unwrap()  \u002F\u002F .unwrap() кидає помилку при провалі\n            \n            console.log('✅ Поїздку створено:', result)\n            router.back()  \u002F\u002F Повертаємось на попередній екран\n        } catch (err) {\n            console.error('❌ Помилка створення:', err)\n        }\n    }\n    \n    return (\n        \u003CView style={{ padding: 20 }}>\n            \u003CTextInput\n                placeholder=\"Назва поїздки\"\n                value={title}\n                onChangeText={setTitle}\n                style={styles.input}\n            \u002F>\n            \n            \u003CTextInput\n                placeholder=\"Регіон\"\n                value={region}\n                onChangeText={setRegion}\n                style={styles.input}\n            \u002F>\n            \n            \u003CButton \n                title={isLoading ? \"Створення...\" : \"Створити поїздку\"}\n                onPress={handleSubmit}\n                disabled={isLoading || !title || !region}\n            \u002F>\n            \n            {error && (\n                \u003CText style={styles.error}>\n                    Помилка: {error.toString()}\n                \u003C\u002FText>\n            )}\n        \u003C\u002FView>\n    )\n}\n",[3829,20244,20245,20250,20264,20294,20308,20324,20328,20339,20352,20356,20361,20388,20392,20414,20436,20440,20457,20464,20469,20483,20490,20497,20513,20527,20531,20550,20565,20579,20598,20602,20606,20610,20616,20641,20647,20655,20667,20679,20697,20701,20705,20711,20720,20732,20744,20760,20764,20768,20776,20798,20812,20838,20842,20846,20856,20878,20894,20902,20908,20916,20920],{"__ignoreMap":3827},[3832,20246,20247],{"class":3834,"line":3835},[3832,20248,20249],{"class":3838},"\u002F\u002F app\u002Fscreens\u002FCreateTripScreen.tsx\n",[3832,20251,20252,20254,20256,20258,20260,20262],{"class":3834,"line":3842},[3832,20253,3846],{"class":3845},[3832,20255,3850],{"class":3849},[3832,20257,7440],{"class":3853},[3832,20259,3863],{"class":3849},[3832,20261,3866],{"class":3845},[3832,20263,4621],{"class":3869},[3832,20265,20266,20268,20270,20272,20274,20276,20278,20280,20282,20284,20286,20288,20290,20292],{"class":3834,"line":3873},[3832,20267,3846],{"class":3845},[3832,20269,3850],{"class":3849},[3832,20271,4630],{"class":3853},[3832,20273,3857],{"class":3849},[3832,20275,7535],{"class":3853},[3832,20277,3857],{"class":3849},[3832,20279,18725],{"class":3853},[3832,20281,3857],{"class":3849},[3832,20283,4635],{"class":3853},[3832,20285,3857],{"class":3849},[3832,20287,4645],{"class":3853},[3832,20289,3863],{"class":3849},[3832,20291,3866],{"class":3845},[3832,20293,4652],{"class":3869},[3832,20295,20296,20298,20300,20302,20304,20306],{"class":3834,"line":3880},[3832,20297,3846],{"class":3845},[3832,20299,3850],{"class":3849},[3832,20301,6504],{"class":3853},[3832,20303,3863],{"class":3849},[3832,20305,3866],{"class":3845},[3832,20307,6537],{"class":3869},[3832,20309,20310,20312,20314,20317,20319,20321],{"class":3834,"line":3886},[3832,20311,3846],{"class":3845},[3832,20313,3850],{"class":3849},[3832,20315,20316],{"class":3853},"useRouter",[3832,20318,3863],{"class":3849},[3832,20320,3866],{"class":3845},[3832,20322,20323],{"class":3869}," 'expo-router'\n",[3832,20325,20326],{"class":3834,"line":3900},[3832,20327,3877],{"emptyLinePlaceholder":3876},[3832,20329,20330,20332,20334,20337],{"class":3834,"line":3912},[3832,20331,4105],{"class":3845},[3832,20333,4699],{"class":3889},[3832,20335,20336],{"class":4117}," CreateTripScreen",[3832,20338,4705],{"class":3849},[3832,20340,20341,20343,20346,20348,20350],{"class":3834,"line":3922},[3832,20342,4710],{"class":3889},[3832,20344,20345],{"class":4042}," router",[3832,20347,4114],{"class":3849},[3832,20349,20316],{"class":4117},[3832,20351,4230],{"class":3849},[3832,20353,20354],{"class":3834,"line":3932},[3832,20355,4724],{"class":3849},[3832,20357,20358],{"class":3834,"line":3942},[3832,20359,20360],{"class":3838},"    \u002F\u002F Хук мутації повертає [функцію-тригер, стан запиту]\n",[3832,20362,20363,20365,20367,20369,20371,20373,20375,20377,20379,20382,20384,20386],{"class":3834,"line":3948},[3832,20364,4710],{"class":3889},[3832,20366,6274],{"class":3849},[3832,20368,5238],{"class":4042},[3832,20370,4611],{"class":3849},[3832,20372,4371],{"class":4042},[3832,20374,3857],{"class":3849},[3832,20376,4386],{"class":4042},[3832,20378,3857],{"class":3849},[3832,20380,20381],{"class":4042},"isSuccess",[3832,20383,19279],{"class":3849},[3832,20385,6504],{"class":4117},[3832,20387,4230],{"class":3849},[3832,20389,20390],{"class":3834,"line":3953},[3832,20391,4724],{"class":3849},[3832,20393,20394,20396,20398,20400,20402,20404,20406,20408,20410,20412],{"class":3834,"line":3959},[3832,20395,4710],{"class":3889},[3832,20397,6274],{"class":3849},[3832,20399,4998],{"class":4042},[3832,20401,3857],{"class":3849},[3832,20403,7434],{"class":4042},[3832,20405,7437],{"class":3849},[3832,20407,7440],{"class":4117},[3832,20409,4162],{"class":3849},[3832,20411,7445],{"class":3869},[3832,20413,4168],{"class":3849},[3832,20415,20416,20418,20420,20422,20424,20426,20428,20430,20432,20434],{"class":3834,"line":3969},[3832,20417,4710],{"class":3889},[3832,20419,6274],{"class":3849},[3832,20421,7456],{"class":4042},[3832,20423,3857],{"class":3849},[3832,20425,7461],{"class":4042},[3832,20427,7437],{"class":3849},[3832,20429,7440],{"class":4117},[3832,20431,4162],{"class":3849},[3832,20433,7445],{"class":3869},[3832,20435,4168],{"class":3849},[3832,20437,20438],{"class":3834,"line":3986},[3832,20439,4724],{"class":3849},[3832,20441,20442,20444,20447,20449,20451,20453,20455],{"class":3834,"line":4000},[3832,20443,4710],{"class":3889},[3832,20445,20446],{"class":4117}," handleSubmit",[3832,20448,4114],{"class":3849},[3832,20450,5477],{"class":3889},[3832,20452,4137],{"class":3849},[3832,20454,4140],{"class":3889},[3832,20456,3897],{"class":3849},[3832,20458,20459,20462],{"class":3834,"line":4020},[3832,20460,20461],{"class":3845},"        try",[3832,20463,3897],{"class":3849},[3832,20465,20466],{"class":3834,"line":4025},[3832,20467,20468],{"class":3838},"            \u002F\u002F Викликаємо мутацію вручну\n",[3832,20470,20471,20473,20475,20477,20479,20481],{"class":3834,"line":4030},[3832,20472,11444],{"class":3889},[3832,20474,13744],{"class":4042},[3832,20476,4114],{"class":3849},[3832,20478,4156],{"class":3845},[3832,20480,5054],{"class":4117},[3832,20482,4267],{"class":3849},[3832,20484,20485,20488],{"class":3834,"line":4036},[3832,20486,20487],{"class":3853},"                title",[3832,20489,4072],{"class":3849},[3832,20491,20492,20495],{"class":3834,"line":4054},[3832,20493,20494],{"class":3853},"                region",[3832,20496,4072],{"class":3849},[3832,20498,20499,20502,20504,20506,20508,20511],{"class":3834,"line":4063},[3832,20500,20501],{"class":3853},"                startDate:",[3832,20503,4198],{"class":3889},[3832,20505,7497],{"class":4117},[3832,20507,9620],{"class":3849},[3832,20509,20510],{"class":4117},"toISOString",[3832,20512,11385],{"class":3849},[3832,20514,20515,20518,20521,20524],{"class":3834,"line":4075},[3832,20516,20517],{"class":3849},"            }).",[3832,20519,20520],{"class":4117},"unwrap",[3832,20522,20523],{"class":3849},"()  ",[3832,20525,20526],{"class":3838},"\u002F\u002F .unwrap() кидає помилку при провалі\n",[3832,20528,20529],{"class":3834,"line":4086},[3832,20530,8518],{"class":3849},[3832,20532,20533,20535,20537,20539,20541,20544,20546,20548],{"class":3834,"line":4091},[3832,20534,13970],{"class":3853},[3832,20536,4183],{"class":3849},[3832,20538,7989],{"class":4117},[3832,20540,4162],{"class":3849},[3832,20542,20543],{"class":3869},"'✅ Поїздку створено:'",[3832,20545,3857],{"class":3849},[3832,20547,13782],{"class":3853},[3832,20549,4168],{"class":3849},[3832,20551,20552,20555,20557,20560,20562],{"class":3834,"line":4096},[3832,20553,20554],{"class":3853},"            router",[3832,20556,4183],{"class":3849},[3832,20558,20559],{"class":4117},"back",[3832,20561,20523],{"class":3849},[3832,20563,20564],{"class":3838},"\u002F\u002F Повертаємось на попередній екран\n",[3832,20566,20567,20569,20572,20574,20577],{"class":3834,"line":4102},[3832,20568,14056],{"class":3849},[3832,20570,20571],{"class":3845},"catch",[3832,20573,4307],{"class":3849},[3832,20575,20576],{"class":3853},"err",[3832,20578,4189],{"class":3849},[3832,20580,20581,20583,20585,20587,20589,20592,20594,20596],{"class":3834,"line":4123},[3832,20582,13970],{"class":3853},[3832,20584,4183],{"class":3849},[3832,20586,4386],{"class":4117},[3832,20588,4162],{"class":3849},[3832,20590,20591],{"class":3869},"'❌ Помилка створення:'",[3832,20593,3857],{"class":3849},[3832,20595,20576],{"class":3853},[3832,20597,4168],{"class":3849},[3832,20599,20600],{"class":3834,"line":4131},[3832,20601,4214],{"class":3849},[3832,20603,20604],{"class":3834,"line":4145},[3832,20605,4236],{"class":3849},[3832,20607,20608],{"class":3834,"line":4171},[3832,20609,4724],{"class":3849},[3832,20611,20612,20614],{"class":3834,"line":4192},[3832,20613,4911],{"class":3845},[3832,20615,4914],{"class":3849},[3832,20617,20618,20620,20622,20624,20626,20628,20630,20633,20635,20637,20639],{"class":3834,"line":4211},[3832,20619,4919],{"class":4834},[3832,20621,4630],{"class":3893},[3832,20623,8467],{"class":4840},[3832,20625,4844],{"class":3849},[3832,20627,4885],{"class":3889},[3832,20629,8474],{"class":4947},[3832,20631,20632],{"class":3853},"padding:",[3832,20634,10440],{"class":5726},[3832,20636,8500],{"class":4947},[3832,20638,4890],{"class":3889},[3832,20640,4898],{"class":4834},[3832,20642,20643,20645],{"class":3834,"line":4217},[3832,20644,7532],{"class":4834},[3832,20646,17051],{"class":3893},[3832,20648,20649,20651,20653],{"class":3834,"line":4233},[3832,20650,7571],{"class":4840},[3832,20652,4844],{"class":3849},[3832,20654,7576],{"class":3869},[3832,20656,20657,20659,20661,20663,20665],{"class":3834,"line":4239},[3832,20658,7543],{"class":4840},[3832,20660,4844],{"class":3849},[3832,20662,4885],{"class":3889},[3832,20664,4998],{"class":3853},[3832,20666,3945],{"class":3889},[3832,20668,20669,20671,20673,20675,20677],{"class":3834,"line":4244},[3832,20670,7558],{"class":4840},[3832,20672,4844],{"class":3849},[3832,20674,4885],{"class":3889},[3832,20676,7434],{"class":3853},[3832,20678,3945],{"class":3889},[3832,20680,20681,20684,20686,20688,20690,20692,20695],{"class":3834,"line":4249},[3832,20682,20683],{"class":4840},"                style",[3832,20685,4844],{"class":3849},[3832,20687,4885],{"class":3889},[3832,20689,9970],{"class":3853},[3832,20691,4183],{"class":4947},[3832,20693,20694],{"class":3853},"input",[3832,20696,3945],{"class":3889},[3832,20698,20699],{"class":3834,"line":4255},[3832,20700,7581],{"class":4834},[3832,20702,20703],{"class":3834,"line":4270},[3832,20704,8518],{"class":3849},[3832,20706,20707,20709],{"class":3834,"line":4281},[3832,20708,7532],{"class":4834},[3832,20710,17051],{"class":3893},[3832,20712,20713,20715,20717],{"class":3834,"line":4289},[3832,20714,7571],{"class":4840},[3832,20716,4844],{"class":3849},[3832,20718,20719],{"class":3869},"\"Регіон\"\n",[3832,20721,20722,20724,20726,20728,20730],{"class":3834,"line":4298},[3832,20723,7543],{"class":4840},[3832,20725,4844],{"class":3849},[3832,20727,4885],{"class":3889},[3832,20729,7456],{"class":3853},[3832,20731,3945],{"class":3889},[3832,20733,20734,20736,20738,20740,20742],{"class":3834,"line":4320},[3832,20735,7558],{"class":4840},[3832,20737,4844],{"class":3849},[3832,20739,4885],{"class":3889},[3832,20741,7461],{"class":3853},[3832,20743,3945],{"class":3889},[3832,20745,20746,20748,20750,20752,20754,20756,20758],{"class":3834,"line":4326},[3832,20747,20683],{"class":4840},[3832,20749,4844],{"class":3849},[3832,20751,4885],{"class":3889},[3832,20753,9970],{"class":3853},[3832,20755,4183],{"class":4947},[3832,20757,20694],{"class":3853},[3832,20759,3945],{"class":3889},[3832,20761,20762],{"class":3834,"line":4332},[3832,20763,7581],{"class":4834},[3832,20765,20766],{"class":3834,"line":4363},[3832,20767,8518],{"class":3849},[3832,20769,20770,20772,20774],{"class":3834,"line":4379},[3832,20771,7532],{"class":4834},[3832,20773,18725],{"class":3893},[3832,20775,7538],{"class":3849},[3832,20777,20778,20780,20782,20784,20786,20788,20791,20793,20796],{"class":3834,"line":4394},[3832,20779,20487],{"class":4840},[3832,20781,4844],{"class":3849},[3832,20783,4885],{"class":3889},[3832,20785,4371],{"class":3853},[3832,20787,8488],{"class":3849},[3832,20789,20790],{"class":3869}," \"Створення...\"",[3832,20792,8494],{"class":3849},[3832,20794,20795],{"class":3869}," \"Створити поїздку\"",[3832,20797,3945],{"class":3889},[3832,20799,20800,20803,20805,20807,20810],{"class":3834,"line":4400},[3832,20801,20802],{"class":4840},"                onPress",[3832,20804,4844],{"class":3849},[3832,20806,4885],{"class":3889},[3832,20808,20809],{"class":3853},"handleSubmit",[3832,20811,3945],{"class":3889},[3832,20813,20814,20817,20819,20821,20823,20826,20828,20830,20832,20834,20836],{"class":3834,"line":4406},[3832,20815,20816],{"class":4840},"                disabled",[3832,20818,4844],{"class":3849},[3832,20820,4885],{"class":3889},[3832,20822,4371],{"class":3853},[3832,20824,20825],{"class":3849}," ||",[3832,20827,18820],{"class":3849},[3832,20829,4998],{"class":3853},[3832,20831,20825],{"class":3849},[3832,20833,18820],{"class":3849},[3832,20835,7456],{"class":3853},[3832,20837,3945],{"class":3889},[3832,20839,20840],{"class":3834,"line":4437},[3832,20841,7581],{"class":4834},[3832,20843,20844],{"class":3834,"line":4451},[3832,20845,8518],{"class":3849},[3832,20847,20848,20850,20852,20854],{"class":3834,"line":4470},[3832,20849,7586],{"class":3889},[3832,20851,4386],{"class":3853},[3832,20853,18261],{"class":3849},[3832,20855,4914],{"class":4947},[3832,20857,20858,20860,20862,20864,20866,20868,20870,20872,20874,20876],{"class":3834,"line":4475},[3832,20859,9984],{"class":4834},[3832,20861,4635],{"class":3893},[3832,20863,8467],{"class":4840},[3832,20865,4844],{"class":3849},[3832,20867,4885],{"class":3889},[3832,20869,9970],{"class":3853},[3832,20871,4183],{"class":4947},[3832,20873,4386],{"class":3853},[3832,20875,4890],{"class":3889},[3832,20877,4898],{"class":4834},[3832,20879,20880,20882,20884,20886,20888,20890,20892],{"class":3834,"line":4481},[3832,20881,10127],{"class":4947},[3832,20883,4885],{"class":3889},[3832,20885,4386],{"class":3853},[3832,20887,4183],{"class":4947},[3832,20889,10136],{"class":4117},[3832,20891,10139],{"class":4947},[3832,20893,3945],{"class":3889},[3832,20895,20896,20898,20900],{"class":3834,"line":4511},[3832,20897,10146],{"class":4834},[3832,20899,4635],{"class":3893},[3832,20901,4898],{"class":4834},[3832,20903,20904,20906],{"class":3834,"line":4524},[3832,20905,10360],{"class":4947},[3832,20907,3945],{"class":3889},[3832,20909,20910,20912,20914],{"class":3834,"line":4552},[3832,20911,7596],{"class":4834},[3832,20913,4630],{"class":3893},[3832,20915,4898],{"class":4834},[3832,20917,20918],{"class":3834,"line":4557},[3832,20919,5018],{"class":3849},[3832,20921,20922],{"class":3834,"line":4563},[3832,20923,3945],{"class":3849},[3801,20925,20926],{},[3770,20927,20928],{},"Життєвий цикл мутації:",[8090,20930,20932],{"alt":20931},"Життєвий цикл mutation",[3822,20933,20935],{"className":8095,"code":20934,"language":8097,"meta":3827,"style":3827},"@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\nskinparam defaultFontName \"Helvetica\"\n\nparticipant \"Користувач\" as User #DBEAFE\nparticipant \"CreateTripScreen\" as Screen #DCFCE7\nparticipant \"createTrip (mutation)\" as Mutation #FED7AA\nparticipant \"RTK Query Cache\" as Cache #FEF3C7\nparticipant \"Backend API\" as API #FECACA\nparticipant \"getTrips (query)\" as Query #E0E7FF\n\nUser -> Screen : Заповнює форму\\nта натискає \"Створити\"\nScreen -> Mutation : createTrip({ title, region })\nMutation -> Mutation : isLoading = true\n\nMutation -> API : POST \u002Ftrips\\n{ title, region, startDate }\nAPI --> Mutation : 201 Created\\n{ id: \"123\", title: \"Париж\", ... }\n\nMutation -> Mutation : isSuccess = true\\nisLoading = false\n\nMutation -> Cache : invalidatesTags: ['Trip']\nnote right of Cache\n    RTK Query бачить, що тег 'Trip'\n    інвалідовано. Шукає всі активні\n    запити з цим тегом.\nend note\n\nCache -> Query : getTrips має тег 'Trip'\\n→ потрібно оновити!\nQuery -> API : GET \u002Ftrips (автоматичний refetch)\nAPI --> Query : 200 OK [список з новою поїздкою]\n\nQuery --> Screen : Оновлює UI на екрані списку\nnote over User, Screen #DCFCE7\n    Користувач повертається назад\n    і одразу бачить нову поїздку!\nend note\n\n@enduml\n",[3829,20936,20937,20941,20945,20949,20953,20957,20962,20967,20972,20977,20981,20986,20990,20995,21000,21005,21009,21014,21019,21023,21028,21032,21037,21042,21047,21052,21057,21061,21065,21070,21075,21080,21084,21089,21094,21099,21104,21108,21112],{"__ignoreMap":3827},[3832,20938,20939],{"class":3834,"line":3835},[3832,20940,8104],{},[3832,20942,20943],{"class":3834,"line":3842},[3832,20944,8109],{},[3832,20946,20947],{"class":3834,"line":3873},[3832,20948,8114],{},[3832,20950,20951],{"class":3834,"line":3880},[3832,20952,8119],{},[3832,20954,20955],{"class":3834,"line":3886},[3832,20956,3877],{"emptyLinePlaceholder":3876},[3832,20958,20959],{"class":3834,"line":3900},[3832,20960,20961],{},"participant \"Користувач\" as User #DBEAFE\n",[3832,20963,20964],{"class":3834,"line":3912},[3832,20965,20966],{},"participant \"CreateTripScreen\" as Screen #DCFCE7\n",[3832,20968,20969],{"class":3834,"line":3922},[3832,20970,20971],{},"participant \"createTrip (mutation)\" as Mutation #FED7AA\n",[3832,20973,20974],{"class":3834,"line":3932},[3832,20975,20976],{},"participant \"RTK Query Cache\" as Cache #FEF3C7\n",[3832,20978,20979],{"class":3834,"line":3942},[3832,20980,13270],{},[3832,20982,20983],{"class":3834,"line":3948},[3832,20984,20985],{},"participant \"getTrips (query)\" as Query #E0E7FF\n",[3832,20987,20988],{"class":3834,"line":3953},[3832,20989,3877],{"emptyLinePlaceholder":3876},[3832,20991,20992],{"class":3834,"line":3959},[3832,20993,20994],{},"User -> Screen : Заповнює форму\\nта натискає \"Створити\"\n",[3832,20996,20997],{"class":3834,"line":3969},[3832,20998,20999],{},"Screen -> Mutation : createTrip({ title, region })\n",[3832,21001,21002],{"class":3834,"line":3986},[3832,21003,21004],{},"Mutation -> Mutation : isLoading = true\n",[3832,21006,21007],{"class":3834,"line":4000},[3832,21008,3877],{"emptyLinePlaceholder":3876},[3832,21010,21011],{"class":3834,"line":4020},[3832,21012,21013],{},"Mutation -> API : POST \u002Ftrips\\n{ title, region, startDate }\n",[3832,21015,21016],{"class":3834,"line":4025},[3832,21017,21018],{},"API --> Mutation : 201 Created\\n{ id: \"123\", title: \"Париж\", ... }\n",[3832,21020,21021],{"class":3834,"line":4030},[3832,21022,3877],{"emptyLinePlaceholder":3876},[3832,21024,21025],{"class":3834,"line":4036},[3832,21026,21027],{},"Mutation -> Mutation : isSuccess = true\\nisLoading = false\n",[3832,21029,21030],{"class":3834,"line":4054},[3832,21031,3877],{"emptyLinePlaceholder":3876},[3832,21033,21034],{"class":3834,"line":4063},[3832,21035,21036],{},"Mutation -> Cache : invalidatesTags: ['Trip']\n",[3832,21038,21039],{"class":3834,"line":4075},[3832,21040,21041],{},"note right of Cache\n",[3832,21043,21044],{"class":3834,"line":4086},[3832,21045,21046],{},"    RTK Query бачить, що тег 'Trip'\n",[3832,21048,21049],{"class":3834,"line":4091},[3832,21050,21051],{},"    інвалідовано. Шукає всі активні\n",[3832,21053,21054],{"class":3834,"line":4096},[3832,21055,21056],{},"    запити з цим тегом.\n",[3832,21058,21059],{"class":3834,"line":4102},[3832,21060,13425],{},[3832,21062,21063],{"class":3834,"line":4123},[3832,21064,3877],{"emptyLinePlaceholder":3876},[3832,21066,21067],{"class":3834,"line":4131},[3832,21068,21069],{},"Cache -> Query : getTrips має тег 'Trip'\\n→ потрібно оновити!\n",[3832,21071,21072],{"class":3834,"line":4145},[3832,21073,21074],{},"Query -> API : GET \u002Ftrips (автоматичний refetch)\n",[3832,21076,21077],{"class":3834,"line":4171},[3832,21078,21079],{},"API --> Query : 200 OK [список з новою поїздкою]\n",[3832,21081,21082],{"class":3834,"line":4192},[3832,21083,3877],{"emptyLinePlaceholder":3876},[3832,21085,21086],{"class":3834,"line":4211},[3832,21087,21088],{},"Query --> Screen : Оновлює UI на екрані списку\n",[3832,21090,21091],{"class":3834,"line":4217},[3832,21092,21093],{},"note over User, Screen #DCFCE7\n",[3832,21095,21096],{"class":3834,"line":4233},[3832,21097,21098],{},"    Користувач повертається назад\n",[3832,21100,21101],{"class":3834,"line":4239},[3832,21102,21103],{},"    і одразу бачить нову поїздку!\n",[3832,21105,21106],{"class":3834,"line":4244},[3832,21107,13425],{},[3832,21109,21110],{"class":3834,"line":4249},[3832,21111,3877],{"emptyLinePlaceholder":3876},[3832,21113,21114],{"class":3834,"line":4255},[3832,21115,8288],{},[3809,21117,21119],{"id":21118},"розуміння-результату-хука-мутації","Розуміння результату хука мутації",[3801,21121,21122],{},"Mutation хук повертає масив з двох елементів:",[3822,21124,21126],{"className":3824,"code":21125,"language":3826,"meta":3827,"style":3827},"const [\n    trigger,      \u002F\u002F Функція для запуску мутації\n    result        \u002F\u002F Об'єкт зі станом\n] = useCreateTripMutation()\n",[3829,21127,21128,21135,21145,21153],{"__ignoreMap":3827},[3832,21129,21130,21132],{"class":3834,"line":3835},[3832,21131,4039],{"class":3889},[3832,21133,21134],{"class":3849}," [\n",[3832,21136,21137,21140,21142],{"class":3834,"line":3842},[3832,21138,21139],{"class":4042},"    trigger",[3832,21141,17983],{"class":3849},[3832,21143,21144],{"class":3838},"\u002F\u002F Функція для запуску мутації\n",[3832,21146,21147,21150],{"class":3834,"line":3873},[3832,21148,21149],{"class":4042},"    result",[3832,21151,21152],{"class":3838},"        \u002F\u002F Об'єкт зі станом\n",[3832,21154,21155,21157,21159],{"class":3834,"line":3880},[3832,21156,7437],{"class":3849},[3832,21158,6504],{"class":4117},[3832,21160,4230],{"class":3849},[3801,21162,21163],{},[3770,21164,21165],{},"Детальний розбір:",[3822,21167,21169],{"className":3824,"code":21168,"language":3826,"meta":3827,"style":3827},"const [createTrip, {\n    data,           \u002F\u002F Відповідь сервера після успіху\n    error,          \u002F\u002F Об'єкт помилки\n    isLoading,      \u002F\u002F true під час виконання запиту\n    isSuccess,      \u002F\u002F true після успішного завершення\n    isError,        \u002F\u002F true при помилці\n    reset,          \u002F\u002F Функція для скидання стану (isSuccess, error)\n}] = useCreateTripMutation()\n",[3829,21170,21171,21181,21190,21200,21209,21218,21226,21236],{"__ignoreMap":3827},[3832,21172,21173,21175,21177,21179],{"class":3834,"line":3835},[3832,21174,4039],{"class":3889},[3832,21176,6274],{"class":3849},[3832,21178,5238],{"class":4042},[3832,21180,5117],{"class":3849},[3832,21182,21183,21185,21187],{"class":3834,"line":3842},[3832,21184,13064],{"class":4042},[3832,21186,17951],{"class":3849},[3832,21188,21189],{"class":3838},"\u002F\u002F Відповідь сервера після успіху\n",[3832,21191,21192,21194,21197],{"class":3834,"line":3873},[3832,21193,4003],{"class":4042},[3832,21195,21196],{"class":3849},",          ",[3832,21198,21199],{"class":3838},"\u002F\u002F Об'єкт помилки\n",[3832,21201,21202,21204,21206],{"class":3834,"line":3880},[3832,21203,3989],{"class":4042},[3832,21205,17983],{"class":3849},[3832,21207,21208],{"class":3838},"\u002F\u002F true під час виконання запиту\n",[3832,21210,21211,21213,21215],{"class":3834,"line":3886},[3832,21212,17938],{"class":4042},[3832,21214,17983],{"class":3849},[3832,21216,21217],{"class":3838},"\u002F\u002F true після успішного завершення\n",[3832,21219,21220,21222,21224],{"class":3834,"line":3900},[3832,21221,17948],{"class":4042},[3832,21223,17930],{"class":3849},[3832,21225,17954],{"class":3838},[3832,21227,21228,21231,21233],{"class":3834,"line":3912},[3832,21229,21230],{"class":4042},"    reset",[3832,21232,21196],{"class":3849},[3832,21234,21235],{"class":3838},"\u002F\u002F Функція для скидання стану (isSuccess, error)\n",[3832,21237,21238,21241,21243],{"class":3834,"line":3922},[3832,21239,21240],{"class":3849},"}] = ",[3832,21242,6504],{"class":4117},[3832,21244,4230],{"class":3849},[3801,21246,21247],{},[3770,21248,21249],{},"Приклад повного життєвого циклу:",[3822,21251,21253],{"className":4592,"code":21252,"language":4594,"meta":3827,"style":3827},"function CreateTripScreen() {\n    const [createTrip, { data, isLoading, isSuccess, isError, error, reset }] = useCreateTripMutation()\n    \n    useEffect(() => {\n        if (isSuccess) {\n            \u002F\u002F Показуємо toast повідомлення\n            Toast.show({\n                type: 'success',\n                text1: 'Успіх!',\n                text2: `Поїздку \"${data?.title}\" створено`,\n            })\n            \n            \u002F\u002F Через 2 секунди скидаємо стан та повертаємось\n            setTimeout(() => {\n                reset()  \u002F\u002F Очищає isSuccess та data\n                router.back()\n            }, 2000)\n        }\n    }, [isSuccess])\n    \n    const handleSubmit = () => {\n        createTrip({ title: 'Париж', region: 'europe', startDate: '2026-09-01' })\n    }\n    \n    return (\n        \u003CView>\n            \u003CButton title=\"Створити\" onPress={handleSubmit} disabled={isLoading} \u002F>\n            \n            {isLoading && \u003CActivityIndicator \u002F>}\n            {isSuccess && \u003CText style={styles.success}>✅ Успішно створено!\u003C\u002FText>}\n            {isError && \u003CText style={styles.error}>❌ {error.toString()}\u003C\u002FText>}\n        \u003C\u002FView>\n    )\n}\n",[3829,21254,21255,21263,21302,21306,21316,21326,21331,21343,21353,21363,21386,21390,21394,21399,21410,21420,21431,21441,21445,21453,21457,21469,21499,21503,21507,21513,21521,21557,21561,21577,21617,21668,21676,21680],{"__ignoreMap":3827},[3832,21256,21257,21259,21261],{"class":3834,"line":3835},[3832,21258,7416],{"class":3889},[3832,21260,20336],{"class":4117},[3832,21262,4705],{"class":3849},[3832,21264,21265,21267,21269,21271,21273,21275,21277,21279,21281,21283,21285,21287,21289,21291,21293,21296,21298,21300],{"class":3834,"line":3842},[3832,21266,4710],{"class":3889},[3832,21268,6274],{"class":3849},[3832,21270,5238],{"class":4042},[3832,21272,4611],{"class":3849},[3832,21274,6565],{"class":4042},[3832,21276,3857],{"class":3849},[3832,21278,4371],{"class":4042},[3832,21280,3857],{"class":3849},[3832,21282,20381],{"class":4042},[3832,21284,3857],{"class":3849},[3832,21286,18517],{"class":4042},[3832,21288,3857],{"class":3849},[3832,21290,4386],{"class":4042},[3832,21292,3857],{"class":3849},[3832,21294,21295],{"class":4042},"reset",[3832,21297,19279],{"class":3849},[3832,21299,6504],{"class":4117},[3832,21301,4230],{"class":3849},[3832,21303,21304],{"class":3834,"line":3873},[3832,21305,4724],{"class":3849},[3832,21307,21308,21310,21312,21314],{"class":3834,"line":3880},[3832,21309,4782],{"class":4117},[3832,21311,4785],{"class":3849},[3832,21313,4140],{"class":3889},[3832,21315,3897],{"class":3849},[3832,21317,21318,21320,21322,21324],{"class":3834,"line":3886},[3832,21319,4174],{"class":3845},[3832,21321,4307],{"class":3849},[3832,21323,20381],{"class":3853},[3832,21325,4189],{"class":3849},[3832,21327,21328],{"class":3834,"line":3900},[3832,21329,21330],{"class":3838},"            \u002F\u002F Показуємо toast повідомлення\n",[3832,21332,21333,21336,21338,21341],{"class":3834,"line":3912},[3832,21334,21335],{"class":3853},"            Toast",[3832,21337,4183],{"class":3849},[3832,21339,21340],{"class":4117},"show",[3832,21342,4267],{"class":3849},[3832,21344,21345,21348,21351],{"class":3834,"line":3922},[3832,21346,21347],{"class":3853},"                type:",[3832,21349,21350],{"class":3869}," 'success'",[3832,21352,4072],{"class":3849},[3832,21354,21355,21358,21361],{"class":3834,"line":3932},[3832,21356,21357],{"class":3853},"                text1:",[3832,21359,21360],{"class":3869}," 'Успіх!'",[3832,21362,4072],{"class":3849},[3832,21364,21365,21368,21371,21373,21375,21377,21379,21381,21384],{"class":3834,"line":3942},[3832,21366,21367],{"class":3853},"                text2:",[3832,21369,21370],{"class":3869}," `Поїздку \"",[3832,21372,11249],{"class":3889},[3832,21374,6565],{"class":3853},[3832,21376,11188],{"class":4947},[3832,21378,4998],{"class":3853},[3832,21380,4890],{"class":3889},[3832,21382,21383],{"class":3869},"\" створено`",[3832,21385,4072],{"class":3849},[3832,21387,21388],{"class":3834,"line":3948},[3832,21389,4397],{"class":3849},[3832,21391,21392],{"class":3834,"line":3953},[3832,21393,8518],{"class":3849},[3832,21395,21396],{"class":3834,"line":3959},[3832,21397,21398],{"class":3838},"            \u002F\u002F Через 2 секунди скидаємо стан та повертаємось\n",[3832,21400,21401,21404,21406,21408],{"class":3834,"line":3969},[3832,21402,21403],{"class":4117},"            setTimeout",[3832,21405,4785],{"class":3849},[3832,21407,4140],{"class":3889},[3832,21409,3897],{"class":3849},[3832,21411,21412,21415,21417],{"class":3834,"line":3986},[3832,21413,21414],{"class":4117},"                reset",[3832,21416,20523],{"class":3849},[3832,21418,21419],{"class":3838},"\u002F\u002F Очищає isSuccess та data\n",[3832,21421,21422,21425,21427,21429],{"class":3834,"line":4000},[3832,21423,21424],{"class":3853},"                router",[3832,21426,4183],{"class":3849},[3832,21428,20559],{"class":4117},[3832,21430,4230],{"class":3849},[3832,21432,21433,21436,21439],{"class":3834,"line":4020},[3832,21434,21435],{"class":3849},"            }, ",[3832,21437,21438],{"class":5726},"2000",[3832,21440,4168],{"class":3849},[3832,21442,21443],{"class":3834,"line":4025},[3832,21444,4214],{"class":3849},[3832,21446,21447,21449,21451],{"class":3834,"line":4030},[3832,21448,4806],{"class":3849},[3832,21450,20381],{"class":3853},[3832,21452,4812],{"class":3849},[3832,21454,21455],{"class":3834,"line":4036},[3832,21456,4724],{"class":3849},[3832,21458,21459,21461,21463,21465,21467],{"class":3834,"line":4054},[3832,21460,4710],{"class":3889},[3832,21462,20446],{"class":4117},[3832,21464,19297],{"class":3849},[3832,21466,4140],{"class":3889},[3832,21468,3897],{"class":3849},[3832,21470,21471,21474,21476,21479,21482,21484,21486,21488,21490,21493,21496],{"class":3834,"line":4063},[3832,21472,21473],{"class":4117},"        createTrip",[3832,21475,4976],{"class":3849},[3832,21477,21478],{"class":3853},"title:",[3832,21480,21481],{"class":3869}," 'Париж'",[3832,21483,3857],{"class":3849},[3832,21485,17188],{"class":3853},[3832,21487,17191],{"class":3869},[3832,21489,3857],{"class":3849},[3832,21491,21492],{"class":3853},"startDate:",[3832,21494,21495],{"class":3869}," '2026-09-01'",[3832,21497,21498],{"class":3849}," })\n",[3832,21500,21501],{"class":3834,"line":4075},[3832,21502,4236],{"class":3849},[3832,21504,21505],{"class":3834,"line":4086},[3832,21506,4724],{"class":3849},[3832,21508,21509,21511],{"class":3834,"line":4091},[3832,21510,4911],{"class":3845},[3832,21512,4914],{"class":3849},[3832,21514,21515,21517,21519],{"class":3834,"line":4096},[3832,21516,4919],{"class":4834},[3832,21518,4630],{"class":3893},[3832,21520,4898],{"class":4834},[3832,21522,21523,21525,21527,21529,21531,21534,21536,21538,21540,21542,21544,21547,21549,21551,21553,21555],{"class":3834,"line":4102},[3832,21524,7532],{"class":4834},[3832,21526,18725],{"class":3893},[3832,21528,18728],{"class":4840},[3832,21530,4844],{"class":3849},[3832,21532,21533],{"class":3869},"\"Створити\"",[3832,21535,18736],{"class":4840},[3832,21537,4844],{"class":3849},[3832,21539,4885],{"class":3889},[3832,21541,20809],{"class":3853},[3832,21543,4890],{"class":3889},[3832,21545,21546],{"class":4840}," disabled",[3832,21548,4844],{"class":3849},[3832,21550,4885],{"class":3889},[3832,21552,4371],{"class":3853},[3832,21554,4890],{"class":3889},[3832,21556,4850],{"class":4834},[3832,21558,21559],{"class":3834,"line":4123},[3832,21560,8518],{"class":3849},[3832,21562,21563,21565,21567,21569,21571,21573,21575],{"class":3834,"line":4131},[3832,21564,7586],{"class":3889},[3832,21566,4371],{"class":3853},[3832,21568,18261],{"class":3849},[3832,21570,4835],{"class":4834},[3832,21572,4645],{"class":3893},[3832,21574,17147],{"class":4834},[3832,21576,3945],{"class":3889},[3832,21578,21579,21581,21583,21585,21587,21589,21591,21593,21595,21597,21599,21602,21604,21606,21609,21611,21613,21615],{"class":3834,"line":4145},[3832,21580,7586],{"class":3889},[3832,21582,20381],{"class":3853},[3832,21584,18261],{"class":3849},[3832,21586,4835],{"class":4834},[3832,21588,4635],{"class":3893},[3832,21590,8467],{"class":4840},[3832,21592,4844],{"class":3849},[3832,21594,4885],{"class":3889},[3832,21596,9970],{"class":3853},[3832,21598,4183],{"class":4947},[3832,21600,21601],{"class":3853},"success",[3832,21603,4890],{"class":3889},[3832,21605,4879],{"class":4834},[3832,21607,21608],{"class":4947},"✅ Успішно створено!",[3832,21610,4893],{"class":4834},[3832,21612,4635],{"class":3893},[3832,21614,4879],{"class":4834},[3832,21616,3945],{"class":3889},[3832,21618,21619,21621,21623,21625,21627,21629,21631,21633,21635,21637,21639,21641,21643,21645,21648,21650,21652,21654,21656,21658,21660,21662,21664,21666],{"class":3834,"line":4171},[3832,21620,7586],{"class":3889},[3832,21622,18517],{"class":3853},[3832,21624,18261],{"class":3849},[3832,21626,4835],{"class":4834},[3832,21628,4635],{"class":3893},[3832,21630,8467],{"class":4840},[3832,21632,4844],{"class":3849},[3832,21634,4885],{"class":3889},[3832,21636,9970],{"class":3853},[3832,21638,4183],{"class":4947},[3832,21640,4386],{"class":3853},[3832,21642,4890],{"class":3889},[3832,21644,4879],{"class":4834},[3832,21646,21647],{"class":4947},"❌ ",[3832,21649,4885],{"class":3889},[3832,21651,4386],{"class":3853},[3832,21653,4183],{"class":4947},[3832,21655,10136],{"class":4117},[3832,21657,10139],{"class":4947},[3832,21659,4890],{"class":3889},[3832,21661,4893],{"class":4834},[3832,21663,4635],{"class":3893},[3832,21665,4879],{"class":4834},[3832,21667,3945],{"class":3889},[3832,21669,21670,21672,21674],{"class":3834,"line":4192},[3832,21671,7596],{"class":4834},[3832,21673,4630],{"class":3893},[3832,21675,4898],{"class":4834},[3832,21677,21678],{"class":3834,"line":4211},[3832,21679,5018],{"class":3849},[3832,21681,21682],{"class":3834,"line":4217},[3832,21683,3945],{"class":3849},[3809,21685,21687],{"id":21686},"рівень-2-patchput-оновлення-існуючих-даних","Рівень 2: PATCH\u002FPUT (Оновлення існуючих даних)",[3801,21689,21690],{},"Для оновлення поїздки потрібно передати ID та нові дані:",[3822,21692,21694],{"className":3824,"code":21693,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fservices\u002FtripsApi.ts\ninterface UpdateTripDto {\n    id: string\n    title?: string\n    region?: string\n}\n\nexport const tripsApi = createApi({\n    \u002F\u002F ... попередня конфігурація\n    endpoints: (builder) => ({\n        updateTrip: builder.mutation\u003CTrip, UpdateTripDto>({\n            query: ({ id, ...patch }) => ({\n                url: `\u002Ftrips\u002F${id}`,\n                method: 'PATCH',  \u002F\u002F або 'PUT' для повного оновлення\n                body: patch,\n            }),\n            invalidatesTags: (_result, _error, { id }) => [\n                { type: 'Trip', id },  \u002F\u002F Інвалідувати конкретну поїздку\n            ],\n        }),\n    }),\n})\n\nexport const { useUpdateTripMutation } = tripsApi\n",[3829,21695,21696,21700,21709,21717,21725,21733,21737,21741,21755,21760,21776,21798,21820,21837,21849,21858,21862,21889,21910,21915,21919,21923,21927,21931],{"__ignoreMap":3827},[3832,21697,21698],{"class":3834,"line":3835},[3832,21699,11022],{"class":3838},[3832,21701,21702,21704,21707],{"class":3834,"line":3842},[3832,21703,3890],{"class":3889},[3832,21705,21706],{"class":3893}," UpdateTripDto",[3832,21708,3897],{"class":3849},[3832,21710,21711,21713,21715],{"class":3834,"line":3873},[3832,21712,3903],{"class":3853},[3832,21714,3906],{"class":3849},[3832,21716,3909],{"class":3893},[3832,21718,21719,21721,21723],{"class":3834,"line":3880},[3832,21720,3915],{"class":3853},[3832,21722,16378],{"class":3849},[3832,21724,3909],{"class":3893},[3832,21726,21727,21729,21731],{"class":3834,"line":3886},[3832,21728,3925],{"class":3853},[3832,21730,16378],{"class":3849},[3832,21732,3909],{"class":3893},[3832,21734,21735],{"class":3834,"line":3900},[3832,21736,3945],{"class":3849},[3832,21738,21739],{"class":3834,"line":3912},[3832,21740,3877],{"emptyLinePlaceholder":3876},[3832,21742,21743,21745,21747,21749,21751,21753],{"class":3834,"line":3922},[3832,21744,4105],{"class":3845},[3832,21746,4108],{"class":3889},[3832,21748,6231],{"class":4042},[3832,21750,4114],{"class":3849},[3832,21752,6153],{"class":4117},[3832,21754,4267],{"class":3849},[3832,21756,21757],{"class":3834,"line":3932},[3832,21758,21759],{"class":3838},"    \u002F\u002F ... попередня конфігурація\n",[3832,21761,21762,21764,21766,21768,21770,21772,21774],{"class":3834,"line":3942},[3832,21763,6288],{"class":4117},[3832,21765,4304],{"class":3853},[3832,21767,4307],{"class":3849},[3832,21769,4310],{"class":3853},[3832,21771,4313],{"class":3849},[3832,21773,4140],{"class":3889},[3832,21775,6301],{"class":3849},[3832,21777,21778,21781,21783,21785,21787,21789,21791,21793,21796],{"class":3834,"line":3948},[3832,21779,21780],{"class":3853},"        updateTrip:",[3832,21782,6314],{"class":3853},[3832,21784,4183],{"class":3849},[3832,21786,6384],{"class":4117},[3832,21788,5084],{"class":3849},[3832,21790,3977],{"class":3893},[3832,21792,3857],{"class":3849},[3832,21794,21795],{"class":3893},"UpdateTripDto",[3832,21797,6332],{"class":3849},[3832,21799,21800,21802,21804,21806,21808,21811,21814,21816,21818],{"class":3834,"line":3953},[3832,21801,6337],{"class":4117},[3832,21803,4304],{"class":3853},[3832,21805,19679],{"class":3849},[3832,21807,4962],{"class":3853},[3832,21809,21810],{"class":3849},", ...",[3832,21812,21813],{"class":3853},"patch",[3832,21815,4981],{"class":3849},[3832,21817,4140],{"class":3889},[3832,21819,6301],{"class":3849},[3832,21821,21822,21824,21827,21829,21831,21833,21835],{"class":3834,"line":3959},[3832,21823,6424],{"class":3853},[3832,21825,21826],{"class":3869}," `\u002Ftrips\u002F",[3832,21828,11249],{"class":3889},[3832,21830,4962],{"class":3853},[3832,21832,4890],{"class":3889},[3832,21834,11514],{"class":3869},[3832,21836,4072],{"class":3849},[3832,21838,21839,21841,21844,21846],{"class":3834,"line":3969},[3832,21840,6433],{"class":3853},[3832,21842,21843],{"class":3869}," 'PATCH'",[3832,21845,11662],{"class":3849},[3832,21847,21848],{"class":3838},"\u002F\u002F або 'PUT' для повного оновлення\n",[3832,21850,21851,21853,21856],{"class":3834,"line":3986},[3832,21852,6442],{"class":3853},[3832,21854,21855],{"class":3853}," patch",[3832,21857,4072],{"class":3849},[3832,21859,21860],{"class":3834,"line":4000},[3832,21861,6452],{"class":3849},[3832,21863,21864,21867,21869,21871,21874,21876,21879,21881,21883,21885,21887],{"class":3834,"line":4020},[3832,21865,21866],{"class":4117},"            invalidatesTags",[3832,21868,4304],{"class":3853},[3832,21870,4307],{"class":3849},[3832,21872,21873],{"class":3853},"_result",[3832,21875,3857],{"class":3849},[3832,21877,21878],{"class":3853},"_error",[3832,21880,4611],{"class":3849},[3832,21882,4962],{"class":3853},[3832,21884,4981],{"class":3849},[3832,21886,4140],{"class":3889},[3832,21888,21134],{"class":3849},[3832,21890,21891,21894,21897,21900,21902,21904,21907],{"class":3834,"line":4025},[3832,21892,21893],{"class":3849},"                { ",[3832,21895,21896],{"class":3853},"type:",[3832,21898,21899],{"class":3869}," 'Trip'",[3832,21901,3857],{"class":3849},[3832,21903,4962],{"class":3853},[3832,21905,21906],{"class":3849}," },  ",[3832,21908,21909],{"class":3838},"\u002F\u002F Інвалідувати конкретну поїздку\n",[3832,21911,21912],{"class":3834,"line":4030},[3832,21913,21914],{"class":3849},"            ],\n",[3832,21916,21917],{"class":3834,"line":4036},[3832,21918,6367],{"class":3849},[3832,21920,21921],{"class":3834,"line":4054},[3832,21922,6475],{"class":3849},[3832,21924,21925],{"class":3834,"line":4063},[3832,21926,4566],{"class":3849},[3832,21928,21929],{"class":3834,"line":4075},[3832,21930,3877],{"emptyLinePlaceholder":3876},[3832,21932,21933,21935,21937,21939,21942,21944],{"class":3834,"line":4086},[3832,21934,4105],{"class":3845},[3832,21936,4108],{"class":3889},[3832,21938,3850],{"class":3849},[3832,21940,21941],{"class":4042},"useUpdateTripMutation",[3832,21943,4748],{"class":3849},[3832,21945,6509],{"class":3853},[3801,21947,21948],{},[3770,21949,16039],{},[3822,21951,21953],{"className":4592,"code":21952,"language":4594,"meta":3827,"style":3827},"function EditTripScreen({ tripId }) {\n    const [updateTrip, { isLoading }] = useUpdateTripMutation()\n    const [title, setTitle] = useState('')\n    \n    const handleSave = async () => {\n        try {\n            await updateTrip({\n                id: tripId,\n                title: title,\n            }).unwrap()\n            \n            Toast.show({ text1: 'Зміни збережено!' })\n        } catch (err) {\n            Toast.show({ type: 'error', text1: 'Не вдалося зберегти' })\n        }\n    }\n    \n    return (\n        \u003CView>\n            \u003CTextInput value={title} onChangeText={setTitle} \u002F>\n            \u003CButton title=\"Зберегти\" onPress={handleSave} disabled={isLoading} \u002F>\n        \u003C\u002FView>\n    )\n}\n",[3829,21954,21955,21968,21987,22009,22013,22030,22036,22045,22055,22064,22072,22076,22094,22106,22130,22134,22138,22142,22148,22156,22185,22221,22229,22233],{"__ignoreMap":3827},[3832,21956,21957,21959,21962,21964,21966],{"class":3834,"line":3835},[3832,21958,7416],{"class":3889},[3832,21960,21961],{"class":4117}," EditTripScreen",[3832,21963,4976],{"class":3849},[3832,21965,8350],{"class":3853},[3832,21967,8353],{"class":3849},[3832,21969,21970,21972,21974,21977,21979,21981,21983,21985],{"class":3834,"line":3842},[3832,21971,4710],{"class":3889},[3832,21973,6274],{"class":3849},[3832,21975,21976],{"class":4042},"updateTrip",[3832,21978,4611],{"class":3849},[3832,21980,4371],{"class":4042},[3832,21982,19279],{"class":3849},[3832,21984,21941],{"class":4117},[3832,21986,4230],{"class":3849},[3832,21988,21989,21991,21993,21995,21997,21999,22001,22003,22005,22007],{"class":3834,"line":3873},[3832,21990,4710],{"class":3889},[3832,21992,6274],{"class":3849},[3832,21994,4998],{"class":4042},[3832,21996,3857],{"class":3849},[3832,21998,7434],{"class":4042},[3832,22000,7437],{"class":3849},[3832,22002,7440],{"class":4117},[3832,22004,4162],{"class":3849},[3832,22006,7445],{"class":3869},[3832,22008,4168],{"class":3849},[3832,22010,22011],{"class":3834,"line":3880},[3832,22012,4724],{"class":3849},[3832,22014,22015,22017,22020,22022,22024,22026,22028],{"class":3834,"line":3886},[3832,22016,4710],{"class":3889},[3832,22018,22019],{"class":4117}," handleSave",[3832,22021,4114],{"class":3849},[3832,22023,5477],{"class":3889},[3832,22025,4137],{"class":3849},[3832,22027,4140],{"class":3889},[3832,22029,3897],{"class":3849},[3832,22031,22032,22034],{"class":3834,"line":3900},[3832,22033,20461],{"class":3845},[3832,22035,3897],{"class":3849},[3832,22037,22038,22040,22043],{"class":3834,"line":3912},[3832,22039,15229],{"class":3845},[3832,22041,22042],{"class":4117}," updateTrip",[3832,22044,4267],{"class":3849},[3832,22046,22047,22050,22053],{"class":3834,"line":3922},[3832,22048,22049],{"class":3853},"                id:",[3832,22051,22052],{"class":3853}," tripId",[3832,22054,4072],{"class":3849},[3832,22056,22057,22060,22062],{"class":3834,"line":3932},[3832,22058,22059],{"class":3853},"                title:",[3832,22061,18728],{"class":3853},[3832,22063,4072],{"class":3849},[3832,22065,22066,22068,22070],{"class":3834,"line":3942},[3832,22067,20517],{"class":3849},[3832,22069,20520],{"class":4117},[3832,22071,4230],{"class":3849},[3832,22073,22074],{"class":3834,"line":3948},[3832,22075,8518],{"class":3849},[3832,22077,22078,22080,22082,22084,22086,22089,22092],{"class":3834,"line":3953},[3832,22079,21335],{"class":3853},[3832,22081,4183],{"class":3849},[3832,22083,21340],{"class":4117},[3832,22085,4976],{"class":3849},[3832,22087,22088],{"class":3853},"text1:",[3832,22090,22091],{"class":3869}," 'Зміни збережено!'",[3832,22093,21498],{"class":3849},[3832,22095,22096,22098,22100,22102,22104],{"class":3834,"line":3959},[3832,22097,14056],{"class":3849},[3832,22099,20571],{"class":3845},[3832,22101,4307],{"class":3849},[3832,22103,20576],{"class":3853},[3832,22105,4189],{"class":3849},[3832,22107,22108,22110,22112,22114,22116,22118,22121,22123,22125,22128],{"class":3834,"line":3969},[3832,22109,21335],{"class":3853},[3832,22111,4183],{"class":3849},[3832,22113,21340],{"class":4117},[3832,22115,4976],{"class":3849},[3832,22117,21896],{"class":3853},[3832,22119,22120],{"class":3869}," 'error'",[3832,22122,3857],{"class":3849},[3832,22124,22088],{"class":3853},[3832,22126,22127],{"class":3869}," 'Не вдалося зберегти'",[3832,22129,21498],{"class":3849},[3832,22131,22132],{"class":3834,"line":3986},[3832,22133,4214],{"class":3849},[3832,22135,22136],{"class":3834,"line":4000},[3832,22137,4236],{"class":3849},[3832,22139,22140],{"class":3834,"line":4020},[3832,22141,4724],{"class":3849},[3832,22143,22144,22146],{"class":3834,"line":4025},[3832,22145,4911],{"class":3845},[3832,22147,4914],{"class":3849},[3832,22149,22150,22152,22154],{"class":3834,"line":4030},[3832,22151,4919],{"class":4834},[3832,22153,4630],{"class":3893},[3832,22155,4898],{"class":4834},[3832,22157,22158,22160,22162,22164,22166,22168,22170,22172,22175,22177,22179,22181,22183],{"class":3834,"line":4036},[3832,22159,7532],{"class":4834},[3832,22161,7535],{"class":3893},[3832,22163,16943],{"class":4840},[3832,22165,4844],{"class":3849},[3832,22167,4885],{"class":3889},[3832,22169,4998],{"class":3853},[3832,22171,4890],{"class":3889},[3832,22173,22174],{"class":4840}," onChangeText",[3832,22176,4844],{"class":3849},[3832,22178,4885],{"class":3889},[3832,22180,7434],{"class":3853},[3832,22182,4890],{"class":3889},[3832,22184,4850],{"class":4834},[3832,22186,22187,22189,22191,22193,22195,22198,22200,22202,22204,22207,22209,22211,22213,22215,22217,22219],{"class":3834,"line":4054},[3832,22188,7532],{"class":4834},[3832,22190,18725],{"class":3893},[3832,22192,18728],{"class":4840},[3832,22194,4844],{"class":3849},[3832,22196,22197],{"class":3869},"\"Зберегти\"",[3832,22199,18736],{"class":4840},[3832,22201,4844],{"class":3849},[3832,22203,4885],{"class":3889},[3832,22205,22206],{"class":3853},"handleSave",[3832,22208,4890],{"class":3889},[3832,22210,21546],{"class":4840},[3832,22212,4844],{"class":3849},[3832,22214,4885],{"class":3889},[3832,22216,4371],{"class":3853},[3832,22218,4890],{"class":3889},[3832,22220,4850],{"class":4834},[3832,22222,22223,22225,22227],{"class":3834,"line":4063},[3832,22224,7596],{"class":4834},[3832,22226,4630],{"class":3893},[3832,22228,4898],{"class":4834},[3832,22230,22231],{"class":3834,"line":4075},[3832,22232,5018],{"class":3849},[3832,22234,22235],{"class":3834,"line":4086},[3832,22236,3945],{"class":3849},[3809,22238,22240],{"id":22239},"рівень-3-delete-видалення-даних","Рівень 3: DELETE (Видалення даних)",[3822,22242,22244],{"className":3824,"code":22243,"language":3826,"meta":3827,"style":3827},"export const tripsApi = createApi({\n    endpoints: (builder) => ({\n        deleteTrip: builder.mutation\u003C{ success: boolean }, string>({\n            query: (tripId) => ({\n                url: `\u002Ftrips\u002F${tripId}`,\n                method: 'DELETE',\n            }),\n            invalidatesTags: (_result, _error, tripId) => [\n                { type: 'Trip', id: tripId },\n                { type: 'Trip', id: 'LIST' },  \u002F\u002F Оновити весь список\n            ],\n        }),\n    }),\n})\n",[3829,22245,22246,22260,22276,22302,22318,22334,22343,22347,22371,22388,22408,22412,22416,22420],{"__ignoreMap":3827},[3832,22247,22248,22250,22252,22254,22256,22258],{"class":3834,"line":3835},[3832,22249,4105],{"class":3845},[3832,22251,4108],{"class":3889},[3832,22253,6231],{"class":4042},[3832,22255,4114],{"class":3849},[3832,22257,6153],{"class":4117},[3832,22259,4267],{"class":3849},[3832,22261,22262,22264,22266,22268,22270,22272,22274],{"class":3834,"line":3842},[3832,22263,6288],{"class":4117},[3832,22265,4304],{"class":3853},[3832,22267,4307],{"class":3849},[3832,22269,4310],{"class":3853},[3832,22271,4313],{"class":3849},[3832,22273,4140],{"class":3889},[3832,22275,6301],{"class":3849},[3832,22277,22278,22281,22283,22285,22287,22289,22291,22293,22295,22298,22300],{"class":3834,"line":3873},[3832,22279,22280],{"class":3853},"        deleteTrip:",[3832,22282,6314],{"class":3853},[3832,22284,4183],{"class":3849},[3832,22286,6384],{"class":4117},[3832,22288,12498],{"class":3849},[3832,22290,21601],{"class":3853},[3832,22292,3906],{"class":3849},[3832,22294,3994],{"class":3893},[3832,22296,22297],{"class":3849}," }, ",[3832,22299,4008],{"class":3893},[3832,22301,6332],{"class":3849},[3832,22303,22304,22306,22308,22310,22312,22314,22316],{"class":3834,"line":3880},[3832,22305,6337],{"class":4117},[3832,22307,4304],{"class":3853},[3832,22309,4307],{"class":3849},[3832,22311,8350],{"class":3853},[3832,22313,4313],{"class":3849},[3832,22315,4140],{"class":3889},[3832,22317,6301],{"class":3849},[3832,22319,22320,22322,22324,22326,22328,22330,22332],{"class":3834,"line":3886},[3832,22321,6424],{"class":3853},[3832,22323,21826],{"class":3869},[3832,22325,11249],{"class":3889},[3832,22327,8350],{"class":3853},[3832,22329,4890],{"class":3889},[3832,22331,11514],{"class":3869},[3832,22333,4072],{"class":3849},[3832,22335,22336,22338,22341],{"class":3834,"line":3900},[3832,22337,6433],{"class":3853},[3832,22339,22340],{"class":3869}," 'DELETE'",[3832,22342,4072],{"class":3849},[3832,22344,22345],{"class":3834,"line":3912},[3832,22346,6452],{"class":3849},[3832,22348,22349,22351,22353,22355,22357,22359,22361,22363,22365,22367,22369],{"class":3834,"line":3922},[3832,22350,21866],{"class":4117},[3832,22352,4304],{"class":3853},[3832,22354,4307],{"class":3849},[3832,22356,21873],{"class":3853},[3832,22358,3857],{"class":3849},[3832,22360,21878],{"class":3853},[3832,22362,3857],{"class":3849},[3832,22364,8350],{"class":3853},[3832,22366,4313],{"class":3849},[3832,22368,4140],{"class":3889},[3832,22370,21134],{"class":3849},[3832,22372,22373,22375,22377,22379,22381,22384,22386],{"class":3834,"line":3932},[3832,22374,21893],{"class":3849},[3832,22376,21896],{"class":3853},[3832,22378,21899],{"class":3869},[3832,22380,3857],{"class":3849},[3832,22382,22383],{"class":3853},"id:",[3832,22385,22052],{"class":3853},[3832,22387,5145],{"class":3849},[3832,22389,22390,22392,22394,22396,22398,22400,22403,22405],{"class":3834,"line":3942},[3832,22391,21893],{"class":3849},[3832,22393,21896],{"class":3853},[3832,22395,21899],{"class":3869},[3832,22397,3857],{"class":3849},[3832,22399,22383],{"class":3853},[3832,22401,22402],{"class":3869}," 'LIST'",[3832,22404,21906],{"class":3849},[3832,22406,22407],{"class":3838},"\u002F\u002F Оновити весь список\n",[3832,22409,22410],{"class":3834,"line":3948},[3832,22411,21914],{"class":3849},[3832,22413,22414],{"class":3834,"line":3953},[3832,22415,6367],{"class":3849},[3832,22417,22418],{"class":3834,"line":3959},[3832,22419,6475],{"class":3849},[3832,22421,22422],{"class":3834,"line":3969},[3832,22423,4566],{"class":3849},[3801,22425,22426],{},[3770,22427,22428],{},"Використання з підтвердженням:",[3822,22430,22432],{"className":4592,"code":22431,"language":4594,"meta":3827,"style":3827},"function TripCard({ trip }) {\n    const [deleteTrip, { isLoading }] = useDeleteTripMutation()\n    \n    const handleDelete = () => {\n        Alert.alert(\n            'Підтвердження',\n            `Видалити поїздку \"${trip.title}\"?`,\n            [\n                { text: 'Скасувати', style: 'cancel' },\n                {\n                    text: 'Видалити',\n                    style: 'destructive',\n                    onPress: async () => {\n                        try {\n                            await deleteTrip(trip.id).unwrap()\n                            Toast.show({ text1: 'Поїздку видалено' })\n                        } catch (err) {\n                            Toast.show({ type: 'error', text1: 'Помилка видалення' })\n                        }\n                    },\n                },\n            ]\n        )\n    }\n    \n    return (\n        \u003CView style={styles.card}>\n            \u003CText>{trip.title}\u003C\u002FText>\n            \u003CButton \n                title={isLoading ? \"...\" : \"🗑️\"}\n                onPress={handleDelete}\n                disabled={isLoading}\n            \u002F>\n        \u003C\u002FView>\n    )\n}\n",[3829,22433,22434,22447,22467,22471,22484,22496,22503,22523,22528,22548,22553,22563,22573,22589,22596,22618,22636,22649,22672,22676,22680,22685,22690,22694,22698,22702,22708,22730,22754,22762,22784,22797,22809,22813,22821,22825],{"__ignoreMap":3827},[3832,22435,22436,22438,22441,22443,22445],{"class":3834,"line":3835},[3832,22437,7416],{"class":3889},[3832,22439,22440],{"class":4117}," TripCard",[3832,22442,4976],{"class":3849},[3832,22444,8412],{"class":3853},[3832,22446,8353],{"class":3849},[3832,22448,22449,22451,22453,22456,22458,22460,22462,22465],{"class":3834,"line":3842},[3832,22450,4710],{"class":3889},[3832,22452,6274],{"class":3849},[3832,22454,22455],{"class":4042},"deleteTrip",[3832,22457,4611],{"class":3849},[3832,22459,4371],{"class":4042},[3832,22461,19279],{"class":3849},[3832,22463,22464],{"class":4117},"useDeleteTripMutation",[3832,22466,4230],{"class":3849},[3832,22468,22469],{"class":3834,"line":3873},[3832,22470,4724],{"class":3849},[3832,22472,22473,22475,22478,22480,22482],{"class":3834,"line":3880},[3832,22474,4710],{"class":3889},[3832,22476,22477],{"class":4117}," handleDelete",[3832,22479,19297],{"class":3849},[3832,22481,4140],{"class":3889},[3832,22483,3897],{"class":3849},[3832,22485,22486,22489,22491,22494],{"class":3834,"line":3886},[3832,22487,22488],{"class":3853},"        Alert",[3832,22490,4183],{"class":3849},[3832,22492,22493],{"class":4117},"alert",[3832,22495,4120],{"class":3849},[3832,22497,22498,22501],{"class":3834,"line":3900},[3832,22499,22500],{"class":3869},"            'Підтвердження'",[3832,22502,4072],{"class":3849},[3832,22504,22505,22508,22510,22512,22514,22516,22518,22521],{"class":3834,"line":3912},[3832,22506,22507],{"class":3869},"            `Видалити поїздку \"",[3832,22509,11249],{"class":3889},[3832,22511,8412],{"class":3853},[3832,22513,4183],{"class":4947},[3832,22515,4998],{"class":3853},[3832,22517,4890],{"class":3889},[3832,22519,22520],{"class":3869},"\"?`",[3832,22522,4072],{"class":3849},[3832,22524,22525],{"class":3834,"line":3922},[3832,22526,22527],{"class":3849},"            [\n",[3832,22529,22530,22532,22535,22538,22540,22543,22546],{"class":3834,"line":3932},[3832,22531,21893],{"class":3849},[3832,22533,22534],{"class":3853},"text:",[3832,22536,22537],{"class":3869}," 'Скасувати'",[3832,22539,3857],{"class":3849},[3832,22541,22542],{"class":3853},"style:",[3832,22544,22545],{"class":3869}," 'cancel'",[3832,22547,5145],{"class":3849},[3832,22549,22550],{"class":3834,"line":3942},[3832,22551,22552],{"class":3849},"                {\n",[3832,22554,22555,22558,22561],{"class":3834,"line":3948},[3832,22556,22557],{"class":3853},"                    text:",[3832,22559,22560],{"class":3869}," 'Видалити'",[3832,22562,4072],{"class":3849},[3832,22564,22565,22568,22571],{"class":3834,"line":3953},[3832,22566,22567],{"class":3853},"                    style:",[3832,22569,22570],{"class":3869}," 'destructive'",[3832,22572,4072],{"class":3849},[3832,22574,22575,22578,22580,22583,22585,22587],{"class":3834,"line":3959},[3832,22576,22577],{"class":4117},"                    onPress",[3832,22579,4304],{"class":3853},[3832,22581,22582],{"class":3889}," async",[3832,22584,4137],{"class":3849},[3832,22586,4140],{"class":3889},[3832,22588,3897],{"class":3849},[3832,22590,22591,22594],{"class":3834,"line":3969},[3832,22592,22593],{"class":3845},"                        try",[3832,22595,3897],{"class":3849},[3832,22597,22598,22601,22604,22606,22608,22610,22612,22614,22616],{"class":3834,"line":3986},[3832,22599,22600],{"class":3845},"                            await",[3832,22602,22603],{"class":4117}," deleteTrip",[3832,22605,4162],{"class":3849},[3832,22607,8412],{"class":3853},[3832,22609,4183],{"class":3849},[3832,22611,4962],{"class":3853},[3832,22613,5621],{"class":3849},[3832,22615,20520],{"class":4117},[3832,22617,4230],{"class":3849},[3832,22619,22620,22623,22625,22627,22629,22631,22634],{"class":3834,"line":4000},[3832,22621,22622],{"class":3853},"                            Toast",[3832,22624,4183],{"class":3849},[3832,22626,21340],{"class":4117},[3832,22628,4976],{"class":3849},[3832,22630,22088],{"class":3853},[3832,22632,22633],{"class":3869}," 'Поїздку видалено'",[3832,22635,21498],{"class":3849},[3832,22637,22638,22641,22643,22645,22647],{"class":3834,"line":4020},[3832,22639,22640],{"class":3849},"                        } ",[3832,22642,20571],{"class":3845},[3832,22644,4307],{"class":3849},[3832,22646,20576],{"class":3853},[3832,22648,4189],{"class":3849},[3832,22650,22651,22653,22655,22657,22659,22661,22663,22665,22667,22670],{"class":3834,"line":4025},[3832,22652,22622],{"class":3853},[3832,22654,4183],{"class":3849},[3832,22656,21340],{"class":4117},[3832,22658,4976],{"class":3849},[3832,22660,21896],{"class":3853},[3832,22662,22120],{"class":3869},[3832,22664,3857],{"class":3849},[3832,22666,22088],{"class":3853},[3832,22668,22669],{"class":3869}," 'Помилка видалення'",[3832,22671,21498],{"class":3849},[3832,22673,22674],{"class":3834,"line":4030},[3832,22675,9050],{"class":3849},[3832,22677,22678],{"class":3834,"line":4036},[3832,22679,15007],{"class":3849},[3832,22681,22682],{"class":3834,"line":4054},[3832,22683,22684],{"class":3849},"                },\n",[3832,22686,22687],{"class":3834,"line":4063},[3832,22688,22689],{"class":3849},"            ]\n",[3832,22691,22692],{"class":3834,"line":4075},[3832,22693,10048],{"class":3849},[3832,22695,22696],{"class":3834,"line":4086},[3832,22697,4236],{"class":3849},[3832,22699,22700],{"class":3834,"line":4091},[3832,22701,4724],{"class":3849},[3832,22703,22704,22706],{"class":3834,"line":4096},[3832,22705,4911],{"class":3845},[3832,22707,4914],{"class":3849},[3832,22709,22710,22712,22714,22716,22718,22720,22722,22724,22726,22728],{"class":3834,"line":4102},[3832,22711,4919],{"class":4834},[3832,22713,4630],{"class":3893},[3832,22715,8467],{"class":4840},[3832,22717,4844],{"class":3849},[3832,22719,4885],{"class":3889},[3832,22721,9970],{"class":3853},[3832,22723,4183],{"class":4947},[3832,22725,3741],{"class":3853},[3832,22727,4890],{"class":3889},[3832,22729,4898],{"class":4834},[3832,22731,22732,22734,22736,22738,22740,22742,22744,22746,22748,22750,22752],{"class":3834,"line":4123},[3832,22733,7532],{"class":4834},[3832,22735,4635],{"class":3893},[3832,22737,4879],{"class":4834},[3832,22739,4885],{"class":3889},[3832,22741,8412],{"class":3853},[3832,22743,4183],{"class":4947},[3832,22745,4998],{"class":3853},[3832,22747,4890],{"class":3889},[3832,22749,4893],{"class":4834},[3832,22751,4635],{"class":3893},[3832,22753,4898],{"class":4834},[3832,22755,22756,22758,22760],{"class":3834,"line":4131},[3832,22757,7532],{"class":4834},[3832,22759,18725],{"class":3893},[3832,22761,7538],{"class":3849},[3832,22763,22764,22766,22768,22770,22772,22774,22777,22779,22782],{"class":3834,"line":4145},[3832,22765,20487],{"class":4840},[3832,22767,4844],{"class":3849},[3832,22769,4885],{"class":3889},[3832,22771,4371],{"class":3853},[3832,22773,8488],{"class":3849},[3832,22775,22776],{"class":3869}," \"...\"",[3832,22778,8494],{"class":3849},[3832,22780,22781],{"class":3869}," \"🗑️\"",[3832,22783,3945],{"class":3889},[3832,22785,22786,22788,22790,22792,22795],{"class":3834,"line":4171},[3832,22787,20802],{"class":4840},[3832,22789,4844],{"class":3849},[3832,22791,4885],{"class":3889},[3832,22793,22794],{"class":3853},"handleDelete",[3832,22796,3945],{"class":3889},[3832,22798,22799,22801,22803,22805,22807],{"class":3834,"line":4192},[3832,22800,20816],{"class":4840},[3832,22802,4844],{"class":3849},[3832,22804,4885],{"class":3889},[3832,22806,4371],{"class":3853},[3832,22808,3945],{"class":3889},[3832,22810,22811],{"class":3834,"line":4211},[3832,22812,7581],{"class":4834},[3832,22814,22815,22817,22819],{"class":3834,"line":4217},[3832,22816,7596],{"class":4834},[3832,22818,4630],{"class":3893},[3832,22820,4898],{"class":4834},[3832,22822,22823],{"class":3834,"line":4233},[3832,22824,5018],{"class":3849},[3832,22826,22827],{"class":3834,"line":4239},[3832,22828,3945],{"class":3849},[3809,22830,22832],{"id":22831},"типові-помилки-та-як-їх-уникнути","Типові помилки та як їх уникнути",[8777,22834,22835,23016,23252],{},[8780,22836,22839,22844,22916,22921],{"icon":22837,"label":22838},"i-lucide-alert-triangle","❌ Помилка 1: Виклик мутації при рендері",[3801,22840,22841],{},[3770,22842,22843],{},"Неправильно:",[3822,22845,22847],{"className":4592,"code":22846,"language":4594,"meta":3827,"style":3827},"function BadComponent() {\n    const [createTrip] = useCreateTripMutation()\n    \n    \u002F\u002F ❌ НІКОЛИ НЕ РОБІТЬ ТАК!\n    createTrip({ title: 'Test' })  \u002F\u002F Виконається при кожному рендері!\n    \n    return \u003CView \u002F>\n}\n",[3829,22848,22849,22858,22872,22876,22881,22898,22902,22912],{"__ignoreMap":3827},[3832,22850,22851,22853,22856],{"class":3834,"line":3835},[3832,22852,7416],{"class":3889},[3832,22854,22855],{"class":4117}," BadComponent",[3832,22857,4705],{"class":3849},[3832,22859,22860,22862,22864,22866,22868,22870],{"class":3834,"line":3842},[3832,22861,4710],{"class":3889},[3832,22863,6274],{"class":3849},[3832,22865,5238],{"class":4042},[3832,22867,7437],{"class":3849},[3832,22869,6504],{"class":4117},[3832,22871,4230],{"class":3849},[3832,22873,22874],{"class":3834,"line":3873},[3832,22875,4724],{"class":3849},[3832,22877,22878],{"class":3834,"line":3880},[3832,22879,22880],{"class":3838},"    \u002F\u002F ❌ НІКОЛИ НЕ РОБІТЬ ТАК!\n",[3832,22882,22883,22886,22888,22890,22893,22895],{"class":3834,"line":3886},[3832,22884,22885],{"class":4117},"    createTrip",[3832,22887,4976],{"class":3849},[3832,22889,21478],{"class":3853},[3832,22891,22892],{"class":3869}," 'Test'",[3832,22894,17235],{"class":3849},[3832,22896,22897],{"class":3838},"\u002F\u002F Виконається при кожному рендері!\n",[3832,22899,22900],{"class":3834,"line":3900},[3832,22901,4724],{"class":3849},[3832,22903,22904,22906,22908,22910],{"class":3834,"line":3912},[3832,22905,4911],{"class":3845},[3832,22907,4835],{"class":4834},[3832,22909,4630],{"class":3893},[3832,22911,4850],{"class":4834},[3832,22913,22914],{"class":3834,"line":3922},[3832,22915,3945],{"class":3849},[3801,22917,22918],{},[3770,22919,22920],{},"Правильно:",[3822,22922,22924],{"className":4592,"code":22923,"language":4594,"meta":3827,"style":3827},"function GoodComponent() {\n    const [createTrip] = useCreateTripMutation()\n    \n    \u002F\u002F ✅ Мутацію викликаємо у відповідь на подію\n    const handlePress = () => {\n        createTrip({ title: 'Test' })\n    }\n    \n    return \u003CButton onPress={handlePress} \u002F>\n}\n",[3829,22925,22926,22935,22949,22953,22958,22971,22983,22987,22991,23012],{"__ignoreMap":3827},[3832,22927,22928,22930,22933],{"class":3834,"line":3835},[3832,22929,7416],{"class":3889},[3832,22931,22932],{"class":4117}," GoodComponent",[3832,22934,4705],{"class":3849},[3832,22936,22937,22939,22941,22943,22945,22947],{"class":3834,"line":3842},[3832,22938,4710],{"class":3889},[3832,22940,6274],{"class":3849},[3832,22942,5238],{"class":4042},[3832,22944,7437],{"class":3849},[3832,22946,6504],{"class":4117},[3832,22948,4230],{"class":3849},[3832,22950,22951],{"class":3834,"line":3873},[3832,22952,4724],{"class":3849},[3832,22954,22955],{"class":3834,"line":3880},[3832,22956,22957],{"class":3838},"    \u002F\u002F ✅ Мутацію викликаємо у відповідь на подію\n",[3832,22959,22960,22962,22965,22967,22969],{"class":3834,"line":3886},[3832,22961,4710],{"class":3889},[3832,22963,22964],{"class":4117}," handlePress",[3832,22966,19297],{"class":3849},[3832,22968,4140],{"class":3889},[3832,22970,3897],{"class":3849},[3832,22972,22973,22975,22977,22979,22981],{"class":3834,"line":3900},[3832,22974,21473],{"class":4117},[3832,22976,4976],{"class":3849},[3832,22978,21478],{"class":3853},[3832,22980,22892],{"class":3869},[3832,22982,21498],{"class":3849},[3832,22984,22985],{"class":3834,"line":3912},[3832,22986,4236],{"class":3849},[3832,22988,22989],{"class":3834,"line":3922},[3832,22990,4724],{"class":3849},[3832,22992,22993,22995,22997,22999,23001,23003,23005,23008,23010],{"class":3834,"line":3932},[3832,22994,4911],{"class":3845},[3832,22996,4835],{"class":4834},[3832,22998,18725],{"class":3893},[3832,23000,18736],{"class":4840},[3832,23002,4844],{"class":3849},[3832,23004,4885],{"class":3889},[3832,23006,23007],{"class":3853},"handlePress",[3832,23009,4890],{"class":3889},[3832,23011,4850],{"class":4834},[3832,23013,23014],{"class":3834,"line":3942},[3832,23015,3945],{"class":3849},[8780,23017,23019,23023,23059,23063],{"icon":22837,"label":23018},"❌ Помилка 2: Забули обробити помилки",[3801,23020,23021],{},[3770,23022,22843],{},[3822,23024,23026],{"className":4592,"code":23025,"language":4594,"meta":3827,"style":3827},"const handleSubmit = () => {\n    \u002F\u002F ❌ Якщо сервер поверне 500 — користувач нічого не побачить\n    createTrip({ title })\n}\n",[3829,23027,23028,23040,23045,23055],{"__ignoreMap":3827},[3832,23029,23030,23032,23034,23036,23038],{"class":3834,"line":3835},[3832,23031,4039],{"class":3889},[3832,23033,20446],{"class":4117},[3832,23035,19297],{"class":3849},[3832,23037,4140],{"class":3889},[3832,23039,3897],{"class":3849},[3832,23041,23042],{"class":3834,"line":3842},[3832,23043,23044],{"class":3838},"    \u002F\u002F ❌ Якщо сервер поверне 500 — користувач нічого не побачить\n",[3832,23046,23047,23049,23051,23053],{"class":3834,"line":3873},[3832,23048,22885],{"class":4117},[3832,23050,4976],{"class":3849},[3832,23052,4998],{"class":3853},[3832,23054,21498],{"class":3849},[3832,23056,23057],{"class":3834,"line":3880},[3832,23058,3945],{"class":3849},[3801,23060,23061],{},[3770,23062,22920],{},[3822,23064,23066],{"className":4592,"code":23065,"language":4594,"meta":3827,"style":3827},"const [createTrip, { isError, error }] = useCreateTripMutation()\n\nconst handleSubmit = async () => {\n    try {\n        await createTrip({ title }).unwrap()\n        Toast.show({ text1: 'Успіх!' })\n    } catch (err) {\n        Toast.show({ type: 'error', text1: 'Помилка створення' })\n    }\n}\n\n\u002F\u002F Або просто показуємо error у UI:\n{isError && \u003CText style={styles.error}>{error.toString()}\u003C\u002FText>}\n",[3829,23067,23068,23090,23094,23110,23117,23135,23152,23164,23187,23191,23195,23199,23204],{"__ignoreMap":3827},[3832,23069,23070,23072,23074,23076,23078,23080,23082,23084,23086,23088],{"class":3834,"line":3835},[3832,23071,4039],{"class":3889},[3832,23073,6274],{"class":3849},[3832,23075,5238],{"class":4042},[3832,23077,4611],{"class":3849},[3832,23079,18517],{"class":4042},[3832,23081,3857],{"class":3849},[3832,23083,4386],{"class":4042},[3832,23085,19279],{"class":3849},[3832,23087,6504],{"class":4117},[3832,23089,4230],{"class":3849},[3832,23091,23092],{"class":3834,"line":3842},[3832,23093,3877],{"emptyLinePlaceholder":3876},[3832,23095,23096,23098,23100,23102,23104,23106,23108],{"class":3834,"line":3873},[3832,23097,4039],{"class":3889},[3832,23099,20446],{"class":4117},[3832,23101,4114],{"class":3849},[3832,23103,5477],{"class":3889},[3832,23105,4137],{"class":3849},[3832,23107,4140],{"class":3889},[3832,23109,3897],{"class":3849},[3832,23111,23112,23115],{"class":3834,"line":3880},[3832,23113,23114],{"class":3845},"    try",[3832,23116,3897],{"class":3849},[3832,23118,23119,23122,23124,23126,23128,23131,23133],{"class":3834,"line":3886},[3832,23120,23121],{"class":3845},"        await",[3832,23123,5054],{"class":4117},[3832,23125,4976],{"class":3849},[3832,23127,4998],{"class":3853},[3832,23129,23130],{"class":3849}," }).",[3832,23132,20520],{"class":4117},[3832,23134,4230],{"class":3849},[3832,23136,23137,23140,23142,23144,23146,23148,23150],{"class":3834,"line":3900},[3832,23138,23139],{"class":3853},"        Toast",[3832,23141,4183],{"class":3849},[3832,23143,21340],{"class":4117},[3832,23145,4976],{"class":3849},[3832,23147,22088],{"class":3853},[3832,23149,21360],{"class":3869},[3832,23151,21498],{"class":3849},[3832,23153,23154,23156,23158,23160,23162],{"class":3834,"line":3912},[3832,23155,6996],{"class":3849},[3832,23157,20571],{"class":3845},[3832,23159,4307],{"class":3849},[3832,23161,20576],{"class":3853},[3832,23163,4189],{"class":3849},[3832,23165,23166,23168,23170,23172,23174,23176,23178,23180,23182,23185],{"class":3834,"line":3922},[3832,23167,23139],{"class":3853},[3832,23169,4183],{"class":3849},[3832,23171,21340],{"class":4117},[3832,23173,4976],{"class":3849},[3832,23175,21896],{"class":3853},[3832,23177,22120],{"class":3869},[3832,23179,3857],{"class":3849},[3832,23181,22088],{"class":3853},[3832,23183,23184],{"class":3869}," 'Помилка створення'",[3832,23186,21498],{"class":3849},[3832,23188,23189],{"class":3834,"line":3932},[3832,23190,4236],{"class":3849},[3832,23192,23193],{"class":3834,"line":3942},[3832,23194,3945],{"class":3849},[3832,23196,23197],{"class":3834,"line":3948},[3832,23198,3877],{"emptyLinePlaceholder":3876},[3832,23200,23201],{"class":3834,"line":3953},[3832,23202,23203],{"class":3838},"\u002F\u002F Або просто показуємо error у UI:\n",[3832,23205,23206,23208,23210,23212,23214,23216,23218,23220,23222,23224,23226,23228,23230,23232,23234,23236,23238,23240,23242,23244,23246,23248,23250],{"class":3834,"line":3959},[3832,23207,4885],{"class":3849},[3832,23209,18517],{"class":3853},[3832,23211,13789],{"class":3849},[3832,23213,5084],{"class":4834},[3832,23215,4635],{"class":3893},[3832,23217,8467],{"class":4840},[3832,23219,4844],{"class":3849},[3832,23221,4885],{"class":3889},[3832,23223,9970],{"class":3853},[3832,23225,4183],{"class":4947},[3832,23227,4386],{"class":3853},[3832,23229,4890],{"class":3889},[3832,23231,4879],{"class":4834},[3832,23233,4885],{"class":3889},[3832,23235,4386],{"class":3853},[3832,23237,4183],{"class":4947},[3832,23239,10136],{"class":4117},[3832,23241,10139],{"class":4947},[3832,23243,4890],{"class":3889},[3832,23245,4893],{"class":4834},[3832,23247,4635],{"class":3893},[3832,23249,4879],{"class":4834},[3832,23251,3945],{"class":3849},[8780,23253,23255,23259,23358,23362],{"icon":22837,"label":23254},"❌ Помилка 3: Не скидаємо стан між викликами",[3801,23256,23257],{},[3770,23258,5420],{},[3822,23260,23262],{"className":4592,"code":23261,"language":4594,"meta":3827,"style":3827},"function CreateScreen() {\n    const [createTrip, { isSuccess }] = useCreateTripMutation()\n    \n    useEffect(() => {\n        if (isSuccess) {\n            router.back()  \u002F\u002F Повертаємось назад\n        }\n    }, [isSuccess])\n    \n    \u002F\u002F Якщо користувач повернеться на цей екран знову,\n    \u002F\u002F isSuccess все ще буде true! Екран одразу закриється\n}\n",[3829,23263,23264,23273,23291,23295,23305,23315,23328,23332,23340,23344,23349,23354],{"__ignoreMap":3827},[3832,23265,23266,23268,23271],{"class":3834,"line":3835},[3832,23267,7416],{"class":3889},[3832,23269,23270],{"class":4117}," CreateScreen",[3832,23272,4705],{"class":3849},[3832,23274,23275,23277,23279,23281,23283,23285,23287,23289],{"class":3834,"line":3842},[3832,23276,4710],{"class":3889},[3832,23278,6274],{"class":3849},[3832,23280,5238],{"class":4042},[3832,23282,4611],{"class":3849},[3832,23284,20381],{"class":4042},[3832,23286,19279],{"class":3849},[3832,23288,6504],{"class":4117},[3832,23290,4230],{"class":3849},[3832,23292,23293],{"class":3834,"line":3873},[3832,23294,4724],{"class":3849},[3832,23296,23297,23299,23301,23303],{"class":3834,"line":3880},[3832,23298,4782],{"class":4117},[3832,23300,4785],{"class":3849},[3832,23302,4140],{"class":3889},[3832,23304,3897],{"class":3849},[3832,23306,23307,23309,23311,23313],{"class":3834,"line":3886},[3832,23308,4174],{"class":3845},[3832,23310,4307],{"class":3849},[3832,23312,20381],{"class":3853},[3832,23314,4189],{"class":3849},[3832,23316,23317,23319,23321,23323,23325],{"class":3834,"line":3900},[3832,23318,20554],{"class":3853},[3832,23320,4183],{"class":3849},[3832,23322,20559],{"class":4117},[3832,23324,20523],{"class":3849},[3832,23326,23327],{"class":3838},"\u002F\u002F Повертаємось назад\n",[3832,23329,23330],{"class":3834,"line":3912},[3832,23331,4214],{"class":3849},[3832,23333,23334,23336,23338],{"class":3834,"line":3922},[3832,23335,4806],{"class":3849},[3832,23337,20381],{"class":3853},[3832,23339,4812],{"class":3849},[3832,23341,23342],{"class":3834,"line":3932},[3832,23343,4724],{"class":3849},[3832,23345,23346],{"class":3834,"line":3942},[3832,23347,23348],{"class":3838},"    \u002F\u002F Якщо користувач повернеться на цей екран знову,\n",[3832,23350,23351],{"class":3834,"line":3948},[3832,23352,23353],{"class":3838},"    \u002F\u002F isSuccess все ще буде true! Екран одразу закриється\n",[3832,23355,23356],{"class":3834,"line":3953},[3832,23357,3945],{"class":3849},[3801,23359,23360],{},[3770,23361,22920],{},[3822,23363,23365],{"className":4592,"code":23364,"language":4594,"meta":3827,"style":3827},"function CreateScreen() {\n    const [createTrip, { isSuccess, reset }] = useCreateTripMutation()\n    \n    useEffect(() => {\n        if (isSuccess) {\n            router.back()\n        }\n    }, [isSuccess])\n    \n    \u002F\u002F Скидаємо стан при розмонтуванні екрана\n    useEffect(() => {\n        return () => reset()\n    }, [])\n}\n",[3829,23366,23367,23375,23397,23401,23411,23421,23431,23435,23443,23447,23452,23462,23475,23480],{"__ignoreMap":3827},[3832,23368,23369,23371,23373],{"class":3834,"line":3835},[3832,23370,7416],{"class":3889},[3832,23372,23270],{"class":4117},[3832,23374,4705],{"class":3849},[3832,23376,23377,23379,23381,23383,23385,23387,23389,23391,23393,23395],{"class":3834,"line":3842},[3832,23378,4710],{"class":3889},[3832,23380,6274],{"class":3849},[3832,23382,5238],{"class":4042},[3832,23384,4611],{"class":3849},[3832,23386,20381],{"class":4042},[3832,23388,3857],{"class":3849},[3832,23390,21295],{"class":4042},[3832,23392,19279],{"class":3849},[3832,23394,6504],{"class":4117},[3832,23396,4230],{"class":3849},[3832,23398,23399],{"class":3834,"line":3873},[3832,23400,4724],{"class":3849},[3832,23402,23403,23405,23407,23409],{"class":3834,"line":3880},[3832,23404,4782],{"class":4117},[3832,23406,4785],{"class":3849},[3832,23408,4140],{"class":3889},[3832,23410,3897],{"class":3849},[3832,23412,23413,23415,23417,23419],{"class":3834,"line":3886},[3832,23414,4174],{"class":3845},[3832,23416,4307],{"class":3849},[3832,23418,20381],{"class":3853},[3832,23420,4189],{"class":3849},[3832,23422,23423,23425,23427,23429],{"class":3834,"line":3900},[3832,23424,20554],{"class":3853},[3832,23426,4183],{"class":3849},[3832,23428,20559],{"class":4117},[3832,23430,4230],{"class":3849},[3832,23432,23433],{"class":3834,"line":3912},[3832,23434,4214],{"class":3849},[3832,23436,23437,23439,23441],{"class":3834,"line":3922},[3832,23438,4806],{"class":3849},[3832,23440,20381],{"class":3853},[3832,23442,4812],{"class":3849},[3832,23444,23445],{"class":3834,"line":3932},[3832,23446,4724],{"class":3849},[3832,23448,23449],{"class":3834,"line":3942},[3832,23450,23451],{"class":3838},"    \u002F\u002F Скидаємо стан при розмонтуванні екрана\n",[3832,23453,23454,23456,23458,23460],{"class":3834,"line":3948},[3832,23455,4782],{"class":4117},[3832,23457,4785],{"class":3849},[3832,23459,4140],{"class":3889},[3832,23461,3897],{"class":3849},[3832,23463,23464,23466,23468,23470,23473],{"class":3834,"line":3953},[3832,23465,4220],{"class":3845},[3832,23467,4137],{"class":3849},[3832,23469,4140],{"class":3889},[3832,23471,23472],{"class":4117}," reset",[3832,23474,4230],{"class":3849},[3832,23476,23477],{"class":3834,"line":3959},[3832,23478,23479],{"class":3849},"    }, [])\n",[3832,23481,23482],{"class":3834,"line":3969},[3832,23483,3945],{"class":3849},[3809,23485,23487],{"id":23486},"просунута-техніка-отримання-даних-одразу-після-мутації","Просунута техніка: Отримання даних одразу після мутації",[3801,23489,23490],{},"Іноді потрібно використати результат мутації для навігації або іншої логіки:",[3822,23492,23494],{"className":4592,"code":23493,"language":4594,"meta":3827,"style":3827},"function CreateTripScreen() {\n    const router = useRouter()\n    const [createTrip] = useCreateTripMutation()\n    \n    const handleSubmit = async () => {\n        try {\n            \u002F\u002F .unwrap() повертає data або кидає помилку\n            const createdTrip = await createTrip({\n                title: 'Париж',\n                region: 'europe',\n                startDate: '2026-09-01',\n            }).unwrap()\n            \n            \u002F\u002F Тепер можемо використати дані\n            console.log('Створено поїздку з ID:', createdTrip.id)\n            \n            \u002F\u002F Навігація на сторінку деталей нової поїздки\n            router.push(`\u002Ftrips\u002F${createdTrip.id}`)\n        } catch (err) {\n            console.error('Помилка:', err)\n        }\n    }\n    \n    return \u003CButton title=\"Створити\" onPress={handleSubmit} \u002F>\n}\n",[3829,23495,23496,23504,23516,23530,23534,23550,23556,23561,23576,23584,23593,23601,23609,23613,23618,23642,23646,23651,23678,23690,23709,23713,23717,23721,23747],{"__ignoreMap":3827},[3832,23497,23498,23500,23502],{"class":3834,"line":3835},[3832,23499,7416],{"class":3889},[3832,23501,20336],{"class":4117},[3832,23503,4705],{"class":3849},[3832,23505,23506,23508,23510,23512,23514],{"class":3834,"line":3842},[3832,23507,4710],{"class":3889},[3832,23509,20345],{"class":4042},[3832,23511,4114],{"class":3849},[3832,23513,20316],{"class":4117},[3832,23515,4230],{"class":3849},[3832,23517,23518,23520,23522,23524,23526,23528],{"class":3834,"line":3873},[3832,23519,4710],{"class":3889},[3832,23521,6274],{"class":3849},[3832,23523,5238],{"class":4042},[3832,23525,7437],{"class":3849},[3832,23527,6504],{"class":4117},[3832,23529,4230],{"class":3849},[3832,23531,23532],{"class":3834,"line":3880},[3832,23533,4724],{"class":3849},[3832,23535,23536,23538,23540,23542,23544,23546,23548],{"class":3834,"line":3886},[3832,23537,4710],{"class":3889},[3832,23539,20446],{"class":4117},[3832,23541,4114],{"class":3849},[3832,23543,5477],{"class":3889},[3832,23545,4137],{"class":3849},[3832,23547,4140],{"class":3889},[3832,23549,3897],{"class":3849},[3832,23551,23552,23554],{"class":3834,"line":3900},[3832,23553,20461],{"class":3845},[3832,23555,3897],{"class":3849},[3832,23557,23558],{"class":3834,"line":3912},[3832,23559,23560],{"class":3838},"            \u002F\u002F .unwrap() повертає data або кидає помилку\n",[3832,23562,23563,23565,23568,23570,23572,23574],{"class":3834,"line":3922},[3832,23564,11444],{"class":3889},[3832,23566,23567],{"class":4042}," createdTrip",[3832,23569,4114],{"class":3849},[3832,23571,4156],{"class":3845},[3832,23573,5054],{"class":4117},[3832,23575,4267],{"class":3849},[3832,23577,23578,23580,23582],{"class":3834,"line":3932},[3832,23579,22059],{"class":3853},[3832,23581,21481],{"class":3869},[3832,23583,4072],{"class":3849},[3832,23585,23586,23589,23591],{"class":3834,"line":3942},[3832,23587,23588],{"class":3853},"                region:",[3832,23590,17191],{"class":3869},[3832,23592,4072],{"class":3849},[3832,23594,23595,23597,23599],{"class":3834,"line":3948},[3832,23596,20501],{"class":3853},[3832,23598,21495],{"class":3869},[3832,23600,4072],{"class":3849},[3832,23602,23603,23605,23607],{"class":3834,"line":3953},[3832,23604,20517],{"class":3849},[3832,23606,20520],{"class":4117},[3832,23608,4230],{"class":3849},[3832,23610,23611],{"class":3834,"line":3959},[3832,23612,8518],{"class":3849},[3832,23614,23615],{"class":3834,"line":3969},[3832,23616,23617],{"class":3838},"            \u002F\u002F Тепер можемо використати дані\n",[3832,23619,23620,23622,23624,23626,23628,23631,23633,23636,23638,23640],{"class":3834,"line":3986},[3832,23621,13970],{"class":3853},[3832,23623,4183],{"class":3849},[3832,23625,7989],{"class":4117},[3832,23627,4162],{"class":3849},[3832,23629,23630],{"class":3869},"'Створено поїздку з ID:'",[3832,23632,3857],{"class":3849},[3832,23634,23635],{"class":3853},"createdTrip",[3832,23637,4183],{"class":3849},[3832,23639,4962],{"class":3853},[3832,23641,4168],{"class":3849},[3832,23643,23644],{"class":3834,"line":4000},[3832,23645,8518],{"class":3849},[3832,23647,23648],{"class":3834,"line":4020},[3832,23649,23650],{"class":3838},"            \u002F\u002F Навігація на сторінку деталей нової поїздки\n",[3832,23652,23653,23655,23657,23659,23661,23664,23666,23668,23670,23672,23674,23676],{"class":3834,"line":4025},[3832,23654,20554],{"class":3853},[3832,23656,4183],{"class":3849},[3832,23658,5327],{"class":4117},[3832,23660,4162],{"class":3849},[3832,23662,23663],{"class":3869},"`\u002Ftrips\u002F",[3832,23665,11249],{"class":3889},[3832,23667,23635],{"class":3853},[3832,23669,4183],{"class":4947},[3832,23671,4962],{"class":3853},[3832,23673,4890],{"class":3889},[3832,23675,11514],{"class":3869},[3832,23677,4168],{"class":3849},[3832,23679,23680,23682,23684,23686,23688],{"class":3834,"line":4030},[3832,23681,14056],{"class":3849},[3832,23683,20571],{"class":3845},[3832,23685,4307],{"class":3849},[3832,23687,20576],{"class":3853},[3832,23689,4189],{"class":3849},[3832,23691,23692,23694,23696,23698,23700,23703,23705,23707],{"class":3834,"line":4036},[3832,23693,13970],{"class":3853},[3832,23695,4183],{"class":3849},[3832,23697,4386],{"class":4117},[3832,23699,4162],{"class":3849},[3832,23701,23702],{"class":3869},"'Помилка:'",[3832,23704,3857],{"class":3849},[3832,23706,20576],{"class":3853},[3832,23708,4168],{"class":3849},[3832,23710,23711],{"class":3834,"line":4054},[3832,23712,4214],{"class":3849},[3832,23714,23715],{"class":3834,"line":4063},[3832,23716,4236],{"class":3849},[3832,23718,23719],{"class":3834,"line":4075},[3832,23720,4724],{"class":3849},[3832,23722,23723,23725,23727,23729,23731,23733,23735,23737,23739,23741,23743,23745],{"class":3834,"line":4086},[3832,23724,4911],{"class":3845},[3832,23726,4835],{"class":4834},[3832,23728,18725],{"class":3893},[3832,23730,18728],{"class":4840},[3832,23732,4844],{"class":3849},[3832,23734,21533],{"class":3869},[3832,23736,18736],{"class":4840},[3832,23738,4844],{"class":3849},[3832,23740,4885],{"class":3889},[3832,23742,20809],{"class":3853},[3832,23744,4890],{"class":3889},[3832,23746,4850],{"class":4834},[3832,23748,23749],{"class":3834,"line":4091},[3832,23750,3945],{"class":3849},[3809,23752,23754],{"id":23753},"порівняння-підходів-unwrap-vs-перевірка-стану","Порівняння підходів: unwrap() vs перевірка стану",[6860,23756,23757,23926],{},[3822,23758,23761],{"className":4592,"code":23759,"filename":23760,"language":4594,"meta":3827,"style":3827},"const [createTrip] = useCreateTripMutation()\n\nconst handleSubmit = async () => {\n    try {\n        const result = await createTrip(data).unwrap()\n        \u002F\u002F Код виконається тільки при успіху\n        console.log('Успіх:', result)\n        router.back()\n    } catch (error) {\n        \u002F\u002F Код виконається при помилці\n        console.error('Помилка:', error)\n        Toast.show({ type: 'error', text1: 'Не вдалося створити' })\n    }\n}\n","Підхід 1: unwrap() + try\u002Fcatch",[3829,23762,23763,23777,23781,23797,23803,23825,23830,23849,23860,23872,23877,23895,23918,23922],{"__ignoreMap":3827},[3832,23764,23765,23767,23769,23771,23773,23775],{"class":3834,"line":3835},[3832,23766,4039],{"class":3889},[3832,23768,6274],{"class":3849},[3832,23770,5238],{"class":4042},[3832,23772,7437],{"class":3849},[3832,23774,6504],{"class":4117},[3832,23776,4230],{"class":3849},[3832,23778,23779],{"class":3834,"line":3842},[3832,23780,3877],{"emptyLinePlaceholder":3876},[3832,23782,23783,23785,23787,23789,23791,23793,23795],{"class":3834,"line":3873},[3832,23784,4039],{"class":3889},[3832,23786,20446],{"class":4117},[3832,23788,4114],{"class":3849},[3832,23790,5477],{"class":3889},[3832,23792,4137],{"class":3849},[3832,23794,4140],{"class":3889},[3832,23796,3897],{"class":3849},[3832,23798,23799,23801],{"class":3834,"line":3880},[3832,23800,23114],{"class":3845},[3832,23802,3897],{"class":3849},[3832,23804,23805,23807,23809,23811,23813,23815,23817,23819,23821,23823],{"class":3834,"line":3886},[3832,23806,4148],{"class":3889},[3832,23808,13744],{"class":4042},[3832,23810,4114],{"class":3849},[3832,23812,4156],{"class":3845},[3832,23814,5054],{"class":4117},[3832,23816,4162],{"class":3849},[3832,23818,6565],{"class":3853},[3832,23820,5621],{"class":3849},[3832,23822,20520],{"class":4117},[3832,23824,4230],{"class":3849},[3832,23826,23827],{"class":3834,"line":3900},[3832,23828,23829],{"class":3838},"        \u002F\u002F Код виконається тільки при успіху\n",[3832,23831,23832,23834,23836,23838,23840,23843,23845,23847],{"class":3834,"line":3912},[3832,23833,13811],{"class":3853},[3832,23835,4183],{"class":3849},[3832,23837,7989],{"class":4117},[3832,23839,4162],{"class":3849},[3832,23841,23842],{"class":3869},"'Успіх:'",[3832,23844,3857],{"class":3849},[3832,23846,13782],{"class":3853},[3832,23848,4168],{"class":3849},[3832,23850,23851,23854,23856,23858],{"class":3834,"line":3922},[3832,23852,23853],{"class":3853},"        router",[3832,23855,4183],{"class":3849},[3832,23857,20559],{"class":4117},[3832,23859,4230],{"class":3849},[3832,23861,23862,23864,23866,23868,23870],{"class":3834,"line":3932},[3832,23863,6996],{"class":3849},[3832,23865,20571],{"class":3845},[3832,23867,4307],{"class":3849},[3832,23869,4386],{"class":3853},[3832,23871,4189],{"class":3849},[3832,23873,23874],{"class":3834,"line":3942},[3832,23875,23876],{"class":3838},"        \u002F\u002F Код виконається при помилці\n",[3832,23878,23879,23881,23883,23885,23887,23889,23891,23893],{"class":3834,"line":3948},[3832,23880,13811],{"class":3853},[3832,23882,4183],{"class":3849},[3832,23884,4386],{"class":4117},[3832,23886,4162],{"class":3849},[3832,23888,23702],{"class":3869},[3832,23890,3857],{"class":3849},[3832,23892,4386],{"class":3853},[3832,23894,4168],{"class":3849},[3832,23896,23897,23899,23901,23903,23905,23907,23909,23911,23913,23916],{"class":3834,"line":3953},[3832,23898,23139],{"class":3853},[3832,23900,4183],{"class":3849},[3832,23902,21340],{"class":4117},[3832,23904,4976],{"class":3849},[3832,23906,21896],{"class":3853},[3832,23908,22120],{"class":3869},[3832,23910,3857],{"class":3849},[3832,23912,22088],{"class":3853},[3832,23914,23915],{"class":3869}," 'Не вдалося створити'",[3832,23917,21498],{"class":3849},[3832,23919,23920],{"class":3834,"line":3959},[3832,23921,4236],{"class":3849},[3832,23923,23924],{"class":3834,"line":3969},[3832,23925,3945],{"class":3849},[3822,23927,23930],{"className":4592,"code":23928,"filename":23929,"language":4594,"meta":3827,"style":3827},"const [createTrip, { isSuccess, isError, error }] = useCreateTripMutation()\n\nconst handleSubmit = () => {\n    createTrip(data)\n}\n\nuseEffect(() => {\n    if (isSuccess) {\n        console.log('Успіх!')\n        router.back()\n    }\n}, [isSuccess])\n\nuseEffect(() => {\n    if (isError) {\n        console.error('Помилка:', error)\n        Toast.show({ type: 'error', text1: 'Не вдалося створити' })\n    }\n}, [isError])\n","Підхід 2: Перевірка isSuccess\u002FisError",[3829,23931,23932,23958,23962,23974,23984,23988,23992,24002,24012,24027,24037,24041,24049,24053,24063,24073,24091,24113,24117],{"__ignoreMap":3827},[3832,23933,23934,23936,23938,23940,23942,23944,23946,23948,23950,23952,23954,23956],{"class":3834,"line":3835},[3832,23935,4039],{"class":3889},[3832,23937,6274],{"class":3849},[3832,23939,5238],{"class":4042},[3832,23941,4611],{"class":3849},[3832,23943,20381],{"class":4042},[3832,23945,3857],{"class":3849},[3832,23947,18517],{"class":4042},[3832,23949,3857],{"class":3849},[3832,23951,4386],{"class":4042},[3832,23953,19279],{"class":3849},[3832,23955,6504],{"class":4117},[3832,23957,4230],{"class":3849},[3832,23959,23960],{"class":3834,"line":3842},[3832,23961,3877],{"emptyLinePlaceholder":3876},[3832,23963,23964,23966,23968,23970,23972],{"class":3834,"line":3873},[3832,23965,4039],{"class":3889},[3832,23967,20446],{"class":4117},[3832,23969,19297],{"class":3849},[3832,23971,4140],{"class":3889},[3832,23973,3897],{"class":3849},[3832,23975,23976,23978,23980,23982],{"class":3834,"line":3880},[3832,23977,22885],{"class":4117},[3832,23979,4162],{"class":3849},[3832,23981,6565],{"class":3853},[3832,23983,4168],{"class":3849},[3832,23985,23986],{"class":3834,"line":3886},[3832,23987,3945],{"class":3849},[3832,23989,23990],{"class":3834,"line":3900},[3832,23991,3877],{"emptyLinePlaceholder":3876},[3832,23993,23994,23996,23998,24000],{"class":3834,"line":3912},[3832,23995,4614],{"class":4117},[3832,23997,4785],{"class":3849},[3832,23999,4140],{"class":3889},[3832,24001,3897],{"class":3849},[3832,24003,24004,24006,24008,24010],{"class":3834,"line":3922},[3832,24005,4821],{"class":3845},[3832,24007,4307],{"class":3849},[3832,24009,20381],{"class":3853},[3832,24011,4189],{"class":3849},[3832,24013,24014,24016,24018,24020,24022,24025],{"class":3834,"line":3932},[3832,24015,13811],{"class":3853},[3832,24017,4183],{"class":3849},[3832,24019,7989],{"class":4117},[3832,24021,4162],{"class":3849},[3832,24023,24024],{"class":3869},"'Успіх!'",[3832,24026,4168],{"class":3849},[3832,24028,24029,24031,24033,24035],{"class":3834,"line":3942},[3832,24030,23853],{"class":3853},[3832,24032,4183],{"class":3849},[3832,24034,20559],{"class":4117},[3832,24036,4230],{"class":3849},[3832,24038,24039],{"class":3834,"line":3948},[3832,24040,4236],{"class":3849},[3832,24042,24043,24045,24047],{"class":3834,"line":3953},[3832,24044,5787],{"class":3849},[3832,24046,20381],{"class":3853},[3832,24048,4812],{"class":3849},[3832,24050,24051],{"class":3834,"line":3959},[3832,24052,3877],{"emptyLinePlaceholder":3876},[3832,24054,24055,24057,24059,24061],{"class":3834,"line":3969},[3832,24056,4614],{"class":4117},[3832,24058,4785],{"class":3849},[3832,24060,4140],{"class":3889},[3832,24062,3897],{"class":3849},[3832,24064,24065,24067,24069,24071],{"class":3834,"line":3986},[3832,24066,4821],{"class":3845},[3832,24068,4307],{"class":3849},[3832,24070,18517],{"class":3853},[3832,24072,4189],{"class":3849},[3832,24074,24075,24077,24079,24081,24083,24085,24087,24089],{"class":3834,"line":4000},[3832,24076,13811],{"class":3853},[3832,24078,4183],{"class":3849},[3832,24080,4386],{"class":4117},[3832,24082,4162],{"class":3849},[3832,24084,23702],{"class":3869},[3832,24086,3857],{"class":3849},[3832,24088,4386],{"class":3853},[3832,24090,4168],{"class":3849},[3832,24092,24093,24095,24097,24099,24101,24103,24105,24107,24109,24111],{"class":3834,"line":4020},[3832,24094,23139],{"class":3853},[3832,24096,4183],{"class":3849},[3832,24098,21340],{"class":4117},[3832,24100,4976],{"class":3849},[3832,24102,21896],{"class":3853},[3832,24104,22120],{"class":3869},[3832,24106,3857],{"class":3849},[3832,24108,22088],{"class":3853},[3832,24110,23915],{"class":3869},[3832,24112,21498],{"class":3849},[3832,24114,24115],{"class":3834,"line":4025},[3832,24116,4236],{"class":3849},[3832,24118,24119,24121,24123],{"class":3834,"line":4030},[3832,24120,5787],{"class":3849},[3832,24122,18517],{"class":3853},[3832,24124,4812],{"class":3849},[3801,24126,24127],{},[3770,24128,24129],{},"Коли використовувати кожен підхід:",[3746,24131,24132,24138],{},[3749,24133,7622,24134,24137],{},[3770,24135,24136],{},"unwrap() + try\u002Fcatch"," — для простої лінійної логіки, коли потрібно щось зробити одразу після успіху",[3749,24139,7622,24140,24143],{},[3770,24141,24142],{},"isSuccess\u002FisError"," — для складніших UI станів, коли потрібно показати індикатори завантаження, анімації тощо",[3793,24145],{},[3796,24147,24149],{"id":24148},"система-тегів-автоматична-інвалідація-кешу","Система тегів: Автоматична інвалідація кешу",[3801,24151,24152,24153,18007,24155,24157],{},"Ви вже бачили ",[3829,24154,12059],{},[3829,24156,12068],{}," у попередніх прикладах. Тепер розберемо цю систему детально — це одна з найпотужніших фішок RTK Query, яка робить синхронізацію даних повністю автоматичною.",[3809,24159,24161],{"id":24160},"проблема-яку-вирішують-теги","Проблема, яку вирішують теги",[3801,24163,24164],{},"Уявіть застосунок без системи тегів:",[3822,24166,24168],{"className":4592,"code":24167,"language":4594,"meta":3827,"style":3827},"\u002F\u002F Екран списку поїздок\nfunction TripsListScreen() {\n    const { data: trips } = useGetTripsQuery()\n    \u002F\u002F Показує 5 поїздок\n}\n\n\u002F\u002F Екран створення нової поїздки\nfunction CreateTripScreen() {\n    const [createTrip] = useCreateTripMutation()\n    \n    const handleSubmit = async () => {\n        await createTrip({ title: 'Париж' })\n        router.back()  \u002F\u002F Повертаємось на список\n    }\n}\n",[3829,24169,24170,24175,24183,24201,24206,24210,24214,24219,24227,24241,24245,24261,24275,24288,24292],{"__ignoreMap":3827},[3832,24171,24172],{"class":3834,"line":3835},[3832,24173,24174],{"class":3838},"\u002F\u002F Екран списку поїздок\n",[3832,24176,24177,24179,24181],{"class":3834,"line":3842},[3832,24178,7416],{"class":3889},[3832,24180,4702],{"class":4117},[3832,24182,4705],{"class":3849},[3832,24184,24185,24187,24189,24191,24193,24195,24197,24199],{"class":3834,"line":3873},[3832,24186,4710],{"class":3889},[3832,24188,3850],{"class":3849},[3832,24190,6565],{"class":3853},[3832,24192,3906],{"class":3849},[3832,24194,4458],{"class":4042},[3832,24196,4748],{"class":3849},[3832,24198,6499],{"class":4117},[3832,24200,4230],{"class":3849},[3832,24202,24203],{"class":3834,"line":3880},[3832,24204,24205],{"class":3838},"    \u002F\u002F Показує 5 поїздок\n",[3832,24207,24208],{"class":3834,"line":3886},[3832,24209,3945],{"class":3849},[3832,24211,24212],{"class":3834,"line":3900},[3832,24213,3877],{"emptyLinePlaceholder":3876},[3832,24215,24216],{"class":3834,"line":3912},[3832,24217,24218],{"class":3838},"\u002F\u002F Екран створення нової поїздки\n",[3832,24220,24221,24223,24225],{"class":3834,"line":3922},[3832,24222,7416],{"class":3889},[3832,24224,20336],{"class":4117},[3832,24226,4705],{"class":3849},[3832,24228,24229,24231,24233,24235,24237,24239],{"class":3834,"line":3932},[3832,24230,4710],{"class":3889},[3832,24232,6274],{"class":3849},[3832,24234,5238],{"class":4042},[3832,24236,7437],{"class":3849},[3832,24238,6504],{"class":4117},[3832,24240,4230],{"class":3849},[3832,24242,24243],{"class":3834,"line":3942},[3832,24244,4724],{"class":3849},[3832,24246,24247,24249,24251,24253,24255,24257,24259],{"class":3834,"line":3948},[3832,24248,4710],{"class":3889},[3832,24250,20446],{"class":4117},[3832,24252,4114],{"class":3849},[3832,24254,5477],{"class":3889},[3832,24256,4137],{"class":3849},[3832,24258,4140],{"class":3889},[3832,24260,3897],{"class":3849},[3832,24262,24263,24265,24267,24269,24271,24273],{"class":3834,"line":3953},[3832,24264,23121],{"class":3845},[3832,24266,5054],{"class":4117},[3832,24268,4976],{"class":3849},[3832,24270,21478],{"class":3853},[3832,24272,21481],{"class":3869},[3832,24274,21498],{"class":3849},[3832,24276,24277,24279,24281,24283,24285],{"class":3834,"line":3959},[3832,24278,23853],{"class":3853},[3832,24280,4183],{"class":3849},[3832,24282,20559],{"class":4117},[3832,24284,20523],{"class":3849},[3832,24286,24287],{"class":3838},"\u002F\u002F Повертаємось на список\n",[3832,24289,24290],{"class":3834,"line":3969},[3832,24291,4236],{"class":3849},[3832,24293,24294],{"class":3834,"line":3986},[3832,24295,3945],{"class":3849},[3801,24297,24298],{},[3770,24299,24300],{},"Що побачить користувач після створення?",[3801,24302,24303],{},"❌ Список все ще показує 5 старих поїздок (нову не видно!)",[3801,24305,24306,24309],{},[3770,24307,24308],{},"Чому?"," RTK Query не знає, що дані застаріли. Список закешований і не оновлюється автоматично.",[3801,24311,24312],{},[3770,24313,24314],{},"Наївне рішення:",[3822,24316,24318],{"className":4592,"code":24317,"language":4594,"meta":3827,"style":3827},"const handleSubmit = async () => {\n    await createTrip({ title: 'Париж' })\n    \n    \u002F\u002F Примусово оновлюємо список вручну\n    dispatch(tripsApi.util.invalidateQuery('getTrips'))\n    \n    router.back()\n}\n",[3829,24319,24320,24336,24350,24354,24359,24386,24390,24401],{"__ignoreMap":3827},[3832,24321,24322,24324,24326,24328,24330,24332,24334],{"class":3834,"line":3835},[3832,24323,4039],{"class":3889},[3832,24325,20446],{"class":4117},[3832,24327,4114],{"class":3849},[3832,24329,5477],{"class":3889},[3832,24331,4137],{"class":3849},[3832,24333,4140],{"class":3889},[3832,24335,3897],{"class":3849},[3832,24337,24338,24340,24342,24344,24346,24348],{"class":3834,"line":3842},[3832,24339,5493],{"class":3845},[3832,24341,5054],{"class":4117},[3832,24343,4976],{"class":3849},[3832,24345,21478],{"class":3853},[3832,24347,21481],{"class":3869},[3832,24349,21498],{"class":3849},[3832,24351,24352],{"class":3834,"line":3873},[3832,24353,4724],{"class":3849},[3832,24355,24356],{"class":3834,"line":3880},[3832,24357,24358],{"class":3838},"    \u002F\u002F Примусово оновлюємо список вручну\n",[3832,24360,24361,24364,24366,24369,24371,24374,24376,24379,24381,24384],{"class":3834,"line":3886},[3832,24362,24363],{"class":4117},"    dispatch",[3832,24365,4162],{"class":3849},[3832,24367,24368],{"class":3853},"tripsApi",[3832,24370,4183],{"class":3849},[3832,24372,24373],{"class":3853},"util",[3832,24375,4183],{"class":3849},[3832,24377,24378],{"class":4117},"invalidateQuery",[3832,24380,4162],{"class":3849},[3832,24382,24383],{"class":3869},"'getTrips'",[3832,24385,5506],{"class":3849},[3832,24387,24388],{"class":3834,"line":3900},[3832,24389,4724],{"class":3849},[3832,24391,24392,24395,24397,24399],{"class":3834,"line":3912},[3832,24393,24394],{"class":3853},"    router",[3832,24396,4183],{"class":3849},[3832,24398,20559],{"class":4117},[3832,24400,4230],{"class":3849},[3832,24402,24403],{"class":3834,"line":3922},[3832,24404,3945],{"class":3849},[3801,24406,24407,24408,24411],{},"Але це означає, що у ",[3770,24409,24410],{},"кожному"," місці, де ви створюєте\u002Fзмінюєте\u002Fвидаляєте поїздки, треба пам'ятати інвалідувати правильні запити. При 10 ендпоінтах це перетворюється на кошмар!",[3809,24413,24415],{"id":24414},"рішення-декларативна-система-тегів","Рішення: Декларативна система тегів",[3801,24417,24418,24419,4304],{},"Замість ручної інвалідації, ми описуємо зв'язки між даними ",[3770,24420,24421],{},"декларативно",[3822,24423,24425],{"className":3824,"code":24424,"language":3826,"meta":3827,"style":3827},"export const tripsApi = createApi({\n    tagTypes: ['Trip'],  \u002F\u002F Реєструємо типи тегів\n    endpoints: (builder) => ({\n        \u002F\u002F Query НАДАЄ дані з тегом 'Trip'\n        getTrips: builder.query\u003CTrip[], void>({\n            query: () => '\u002Ftrips',\n            providesTags: ['Trip'],\n        }),\n        \n        \u002F\u002F Mutation ІНВАЛІДУЄ тег 'Trip'\n        createTrip: builder.mutation\u003CTrip, CreateTripDto>({\n            query: (newTrip) => ({\n                url: '\u002Ftrips',\n                method: 'POST',\n                body: newTrip,\n            }),\n            invalidatesTags: ['Trip'],\n        }),\n    }),\n})\n",[3829,24426,24427,24441,24454,24470,24475,24495,24509,24519,24523,24527,24532,24552,24568,24576,24584,24592,24596,24606,24610,24614],{"__ignoreMap":3827},[3832,24428,24429,24431,24433,24435,24437,24439],{"class":3834,"line":3835},[3832,24430,4105],{"class":3845},[3832,24432,4108],{"class":3889},[3832,24434,6231],{"class":4042},[3832,24436,4114],{"class":3849},[3832,24438,6153],{"class":4117},[3832,24440,4267],{"class":3849},[3832,24442,24443,24445,24447,24449,24451],{"class":3834,"line":3842},[3832,24444,6271],{"class":3853},[3832,24446,6274],{"class":3849},[3832,24448,6277],{"class":3869},[3832,24450,6280],{"class":3849},[3832,24452,24453],{"class":3838},"\u002F\u002F Реєструємо типи тегів\n",[3832,24455,24456,24458,24460,24462,24464,24466,24468],{"class":3834,"line":3873},[3832,24457,6288],{"class":4117},[3832,24459,4304],{"class":3853},[3832,24461,4307],{"class":3849},[3832,24463,4310],{"class":3853},[3832,24465,4313],{"class":3849},[3832,24467,4140],{"class":3889},[3832,24469,6301],{"class":3849},[3832,24471,24472],{"class":3834,"line":3880},[3832,24473,24474],{"class":3838},"        \u002F\u002F Query НАДАЄ дані з тегом 'Trip'\n",[3832,24476,24477,24479,24481,24483,24485,24487,24489,24491,24493],{"class":3834,"line":3886},[3832,24478,6311],{"class":3853},[3832,24480,6314],{"class":3853},[3832,24482,4183],{"class":3849},[3832,24484,6319],{"class":4117},[3832,24486,5084],{"class":3849},[3832,24488,3977],{"class":3893},[3832,24490,6326],{"class":3849},[3832,24492,6329],{"class":3893},[3832,24494,6332],{"class":3849},[3832,24496,24497,24499,24501,24503,24505,24507],{"class":3834,"line":3900},[3832,24498,6337],{"class":4117},[3832,24500,4304],{"class":3853},[3832,24502,4137],{"class":3849},[3832,24504,4140],{"class":3889},[3832,24506,6346],{"class":3869},[3832,24508,4072],{"class":3849},[3832,24510,24511,24513,24515,24517],{"class":3834,"line":3912},[3832,24512,6353],{"class":3853},[3832,24514,6274],{"class":3849},[3832,24516,6277],{"class":3869},[3832,24518,11605],{"class":3849},[3832,24520,24521],{"class":3834,"line":3922},[3832,24522,6367],{"class":3849},[3832,24524,24525],{"class":3834,"line":3932},[3832,24526,11390],{"class":3849},[3832,24528,24529],{"class":3834,"line":3942},[3832,24530,24531],{"class":3838},"        \u002F\u002F Mutation ІНВАЛІДУЄ тег 'Trip'\n",[3832,24533,24534,24536,24538,24540,24542,24544,24546,24548,24550],{"class":3834,"line":3948},[3832,24535,6377],{"class":3853},[3832,24537,6314],{"class":3853},[3832,24539,4183],{"class":3849},[3832,24541,6384],{"class":4117},[3832,24543,5084],{"class":3849},[3832,24545,3977],{"class":3893},[3832,24547,3857],{"class":3849},[3832,24549,20142],{"class":3893},[3832,24551,6332],{"class":3849},[3832,24553,24554,24556,24558,24560,24562,24564,24566],{"class":3834,"line":3953},[3832,24555,6337],{"class":4117},[3832,24557,4304],{"class":3853},[3832,24559,4307],{"class":3849},[3832,24561,5076],{"class":3853},[3832,24563,4313],{"class":3849},[3832,24565,4140],{"class":3889},[3832,24567,6301],{"class":3849},[3832,24569,24570,24572,24574],{"class":3834,"line":3959},[3832,24571,6424],{"class":3853},[3832,24573,6346],{"class":3869},[3832,24575,4072],{"class":3849},[3832,24577,24578,24580,24582],{"class":3834,"line":3969},[3832,24579,6433],{"class":3853},[3832,24581,5125],{"class":3869},[3832,24583,4072],{"class":3849},[3832,24585,24586,24588,24590],{"class":3834,"line":3986},[3832,24587,6442],{"class":3853},[3832,24589,6445],{"class":3853},[3832,24591,4072],{"class":3849},[3832,24593,24594],{"class":3834,"line":4000},[3832,24595,6452],{"class":3849},[3832,24597,24598,24600,24602,24604],{"class":3834,"line":4020},[3832,24599,6457],{"class":3853},[3832,24601,6274],{"class":3849},[3832,24603,6277],{"class":3869},[3832,24605,11605],{"class":3849},[3832,24607,24608],{"class":3834,"line":4025},[3832,24609,6367],{"class":3849},[3832,24611,24612],{"class":3834,"line":4030},[3832,24613,6475],{"class":3849},[3832,24615,24616],{"class":3834,"line":4036},[3832,24617,4566],{"class":3849},[3801,24619,24620],{},[3770,24621,24622],{},"Магія:",[8090,24624,24626],{"alt":24625},"Система тегів - базовий потік",[3822,24627,24629],{"className":8095,"code":24628,"language":8097,"meta":3827,"style":3827},"@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\nskinparam defaultFontName \"Helvetica\"\n\nparticipant \"TripsListScreen\" as List #DBEAFE\nparticipant \"getTrips query\" as Query #DCFCE7\nparticipant \"RTK Query Cache\" as Cache #FEF3C7\nparticipant \"createTrip mutation\" as Mutation #FED7AA\n\nList -> Query : useGetTripsQuery()\nQuery -> Cache : Зберігає дані з тегом 'Trip'\nnote right of Cache\n    Cache = {\n        getTrips: {\n            data: [...],\n            tags: ['Trip']\n        }\n    }\nend note\n\nMutation -> Mutation : Користувач створює поїздку\nMutation -> Cache : invalidatesTags: ['Trip']\n\nCache -> Cache : Шукає всі запити з тегом 'Trip'\nCache -> Query : Знайдено getTrips з тегом 'Trip'\\n→ Позначити як STALE\n\nQuery -> Query : Автоматичний refetch\nQuery --> List : Оновлює UI зі свіжими даними\n\n@enduml\n",[3829,24630,24631,24635,24639,24643,24647,24651,24656,24661,24665,24670,24674,24679,24684,24688,24693,24698,24703,24708,24712,24716,24720,24724,24729,24733,24737,24742,24747,24751,24756,24761,24765],{"__ignoreMap":3827},[3832,24632,24633],{"class":3834,"line":3835},[3832,24634,8104],{},[3832,24636,24637],{"class":3834,"line":3842},[3832,24638,8109],{},[3832,24640,24641],{"class":3834,"line":3873},[3832,24642,8114],{},[3832,24644,24645],{"class":3834,"line":3880},[3832,24646,8119],{},[3832,24648,24649],{"class":3834,"line":3886},[3832,24650,3877],{"emptyLinePlaceholder":3876},[3832,24652,24653],{"class":3834,"line":3900},[3832,24654,24655],{},"participant \"TripsListScreen\" as List #DBEAFE\n",[3832,24657,24658],{"class":3834,"line":3912},[3832,24659,24660],{},"participant \"getTrips query\" as Query #DCFCE7\n",[3832,24662,24663],{"class":3834,"line":3922},[3832,24664,20976],{},[3832,24666,24667],{"class":3834,"line":3932},[3832,24668,24669],{},"participant \"createTrip mutation\" as Mutation #FED7AA\n",[3832,24671,24672],{"class":3834,"line":3942},[3832,24673,3877],{"emptyLinePlaceholder":3876},[3832,24675,24676],{"class":3834,"line":3948},[3832,24677,24678],{},"List -> Query : useGetTripsQuery()\n",[3832,24680,24681],{"class":3834,"line":3953},[3832,24682,24683],{},"Query -> Cache : Зберігає дані з тегом 'Trip'\n",[3832,24685,24686],{"class":3834,"line":3959},[3832,24687,21041],{},[3832,24689,24690],{"class":3834,"line":3969},[3832,24691,24692],{},"    Cache = {\n",[3832,24694,24695],{"class":3834,"line":3986},[3832,24696,24697],{},"        getTrips: {\n",[3832,24699,24700],{"class":3834,"line":4000},[3832,24701,24702],{},"            data: [...],\n",[3832,24704,24705],{"class":3834,"line":4020},[3832,24706,24707],{},"            tags: ['Trip']\n",[3832,24709,24710],{"class":3834,"line":4025},[3832,24711,4214],{},[3832,24713,24714],{"class":3834,"line":4030},[3832,24715,4236],{},[3832,24717,24718],{"class":3834,"line":4036},[3832,24719,13425],{},[3832,24721,24722],{"class":3834,"line":4054},[3832,24723,3877],{"emptyLinePlaceholder":3876},[3832,24725,24726],{"class":3834,"line":4063},[3832,24727,24728],{},"Mutation -> Mutation : Користувач створює поїздку\n",[3832,24730,24731],{"class":3834,"line":4075},[3832,24732,21036],{},[3832,24734,24735],{"class":3834,"line":4086},[3832,24736,3877],{"emptyLinePlaceholder":3876},[3832,24738,24739],{"class":3834,"line":4091},[3832,24740,24741],{},"Cache -> Cache : Шукає всі запити з тегом 'Trip'\n",[3832,24743,24744],{"class":3834,"line":4096},[3832,24745,24746],{},"Cache -> Query : Знайдено getTrips з тегом 'Trip'\\n→ Позначити як STALE\n",[3832,24748,24749],{"class":3834,"line":4102},[3832,24750,3877],{"emptyLinePlaceholder":3876},[3832,24752,24753],{"class":3834,"line":4123},[3832,24754,24755],{},"Query -> Query : Автоматичний refetch\n",[3832,24757,24758],{"class":3834,"line":4131},[3832,24759,24760],{},"Query --> List : Оновлює UI зі свіжими даними\n",[3832,24762,24763],{"class":3834,"line":4145},[3832,24764,3877],{"emptyLinePlaceholder":3876},[3832,24766,24767],{"class":3834,"line":4171},[3832,24768,8288],{},[3801,24770,24771,24772,24775],{},"Тепер при створенні поїздки список ",[3770,24773,24774],{},"автоматично"," оновиться без жодного ручного коду!",[3809,24777,24779],{"id":24778},"рівень-1-прості-теги-за-типом","Рівень 1: Прості теги (за типом)",[3801,24781,24782],{},"Це найпростіший випадок — один тег для всього:",[3822,24784,24786],{"className":3824,"code":24785,"language":3826,"meta":3827,"style":3827},"export const tripsApi = createApi({\n    tagTypes: ['Trip'],\n    endpoints: (builder) => ({\n        getTrips: builder.query\u003CTrip[], void>({\n            query: () => '\u002Ftrips',\n            providesTags: ['Trip'],  \u002F\u002F Надає тег\n        }),\n        \n        createTrip: builder.mutation\u003CTrip, CreateTripDto>({\n            query: (data) => ({ url: '\u002Ftrips', method: 'POST', body: data }),\n            invalidatesTags: ['Trip'],  \u002F\u002F Інвалідує тег\n        }),\n        \n        updateTrip: builder.mutation\u003CTrip, { id: string; title: string }>({\n            query: ({ id, ...data }) => ({ url: `\u002Ftrips\u002F${id}`, method: 'PATCH', body: data }),\n            invalidatesTags: ['Trip'],  \u002F\u002F Інвалідує тег\n        }),\n        \n        deleteTrip: builder.mutation\u003Cvoid, string>({\n            query: (id) => ({ url: `\u002Ftrips\u002F${id}`, method: 'DELETE' }),\n            invalidatesTags: ['Trip'],  \u002F\u002F Інвалідує тег\n        }),\n    }),\n})\n",[3829,24787,24788,24802,24812,24828,24848,24862,24875,24879,24883,24903,24940,24953,24957,24961,24994,25040,25052,25056,25060,25080,25116,25128,25132,25136],{"__ignoreMap":3827},[3832,24789,24790,24792,24794,24796,24798,24800],{"class":3834,"line":3835},[3832,24791,4105],{"class":3845},[3832,24793,4108],{"class":3889},[3832,24795,6231],{"class":4042},[3832,24797,4114],{"class":3849},[3832,24799,6153],{"class":4117},[3832,24801,4267],{"class":3849},[3832,24803,24804,24806,24808,24810],{"class":3834,"line":3842},[3832,24805,6271],{"class":3853},[3832,24807,6274],{"class":3849},[3832,24809,6277],{"class":3869},[3832,24811,11605],{"class":3849},[3832,24813,24814,24816,24818,24820,24822,24824,24826],{"class":3834,"line":3873},[3832,24815,6288],{"class":4117},[3832,24817,4304],{"class":3853},[3832,24819,4307],{"class":3849},[3832,24821,4310],{"class":3853},[3832,24823,4313],{"class":3849},[3832,24825,4140],{"class":3889},[3832,24827,6301],{"class":3849},[3832,24829,24830,24832,24834,24836,24838,24840,24842,24844,24846],{"class":3834,"line":3880},[3832,24831,6311],{"class":3853},[3832,24833,6314],{"class":3853},[3832,24835,4183],{"class":3849},[3832,24837,6319],{"class":4117},[3832,24839,5084],{"class":3849},[3832,24841,3977],{"class":3893},[3832,24843,6326],{"class":3849},[3832,24845,6329],{"class":3893},[3832,24847,6332],{"class":3849},[3832,24849,24850,24852,24854,24856,24858,24860],{"class":3834,"line":3886},[3832,24851,6337],{"class":4117},[3832,24853,4304],{"class":3853},[3832,24855,4137],{"class":3849},[3832,24857,4140],{"class":3889},[3832,24859,6346],{"class":3869},[3832,24861,4072],{"class":3849},[3832,24863,24864,24866,24868,24870,24872],{"class":3834,"line":3900},[3832,24865,6353],{"class":3853},[3832,24867,6274],{"class":3849},[3832,24869,6277],{"class":3869},[3832,24871,6280],{"class":3849},[3832,24873,24874],{"class":3838},"\u002F\u002F Надає тег\n",[3832,24876,24877],{"class":3834,"line":3912},[3832,24878,6367],{"class":3849},[3832,24880,24881],{"class":3834,"line":3922},[3832,24882,11390],{"class":3849},[3832,24884,24885,24887,24889,24891,24893,24895,24897,24899,24901],{"class":3834,"line":3932},[3832,24886,6377],{"class":3853},[3832,24888,6314],{"class":3853},[3832,24890,4183],{"class":3849},[3832,24892,6384],{"class":4117},[3832,24894,5084],{"class":3849},[3832,24896,3977],{"class":3893},[3832,24898,3857],{"class":3849},[3832,24900,20142],{"class":3893},[3832,24902,6332],{"class":3849},[3832,24904,24905,24907,24909,24911,24913,24915,24917,24919,24922,24924,24926,24929,24931,24933,24936,24938],{"class":3834,"line":3942},[3832,24906,6337],{"class":4117},[3832,24908,4304],{"class":3853},[3832,24910,4307],{"class":3849},[3832,24912,6565],{"class":3853},[3832,24914,4313],{"class":3849},[3832,24916,4140],{"class":3889},[3832,24918,19679],{"class":3849},[3832,24920,24921],{"class":3853},"url:",[3832,24923,6346],{"class":3869},[3832,24925,3857],{"class":3849},[3832,24927,24928],{"class":3853},"method:",[3832,24930,5125],{"class":3869},[3832,24932,3857],{"class":3849},[3832,24934,24935],{"class":3853},"body:",[3832,24937,18279],{"class":3853},[3832,24939,6266],{"class":3849},[3832,24941,24942,24944,24946,24948,24950],{"class":3834,"line":3948},[3832,24943,6457],{"class":3853},[3832,24945,6274],{"class":3849},[3832,24947,6277],{"class":3869},[3832,24949,6280],{"class":3849},[3832,24951,24952],{"class":3838},"\u002F\u002F Інвалідує тег\n",[3832,24954,24955],{"class":3834,"line":3953},[3832,24956,6367],{"class":3849},[3832,24958,24959],{"class":3834,"line":3959},[3832,24960,11390],{"class":3849},[3832,24962,24963,24965,24967,24969,24971,24973,24975,24977,24979,24981,24983,24985,24987,24989,24991],{"class":3834,"line":3969},[3832,24964,21780],{"class":3853},[3832,24966,6314],{"class":3853},[3832,24968,4183],{"class":3849},[3832,24970,6384],{"class":4117},[3832,24972,5084],{"class":3849},[3832,24974,3977],{"class":3893},[3832,24976,4611],{"class":3849},[3832,24978,4962],{"class":3853},[3832,24980,3906],{"class":3849},[3832,24982,4008],{"class":3893},[3832,24984,12378],{"class":3849},[3832,24986,4998],{"class":3853},[3832,24988,3906],{"class":3849},[3832,24990,4008],{"class":3893},[3832,24992,24993],{"class":3849}," }>({\n",[3832,24995,24996,24998,25000,25002,25004,25006,25008,25010,25012,25014,25016,25018,25020,25022,25024,25026,25028,25030,25032,25034,25036,25038],{"class":3834,"line":3986},[3832,24997,6337],{"class":4117},[3832,24999,4304],{"class":3853},[3832,25001,19679],{"class":3849},[3832,25003,4962],{"class":3853},[3832,25005,21810],{"class":3849},[3832,25007,6565],{"class":3853},[3832,25009,4981],{"class":3849},[3832,25011,4140],{"class":3889},[3832,25013,19679],{"class":3849},[3832,25015,24921],{"class":3853},[3832,25017,21826],{"class":3869},[3832,25019,11249],{"class":3889},[3832,25021,4962],{"class":3853},[3832,25023,4890],{"class":3889},[3832,25025,11514],{"class":3869},[3832,25027,3857],{"class":3849},[3832,25029,24928],{"class":3853},[3832,25031,21843],{"class":3869},[3832,25033,3857],{"class":3849},[3832,25035,24935],{"class":3853},[3832,25037,18279],{"class":3853},[3832,25039,6266],{"class":3849},[3832,25041,25042,25044,25046,25048,25050],{"class":3834,"line":4000},[3832,25043,6457],{"class":3853},[3832,25045,6274],{"class":3849},[3832,25047,6277],{"class":3869},[3832,25049,6280],{"class":3849},[3832,25051,24952],{"class":3838},[3832,25053,25054],{"class":3834,"line":4020},[3832,25055,6367],{"class":3849},[3832,25057,25058],{"class":3834,"line":4025},[3832,25059,11390],{"class":3849},[3832,25061,25062,25064,25066,25068,25070,25072,25074,25076,25078],{"class":3834,"line":4030},[3832,25063,22280],{"class":3853},[3832,25065,6314],{"class":3853},[3832,25067,4183],{"class":3849},[3832,25069,6384],{"class":4117},[3832,25071,5084],{"class":3849},[3832,25073,6329],{"class":3893},[3832,25075,3857],{"class":3849},[3832,25077,4008],{"class":3893},[3832,25079,6332],{"class":3849},[3832,25081,25082,25084,25086,25088,25090,25092,25094,25096,25098,25100,25102,25104,25106,25108,25110,25112,25114],{"class":3834,"line":4036},[3832,25083,6337],{"class":4117},[3832,25085,4304],{"class":3853},[3832,25087,4307],{"class":3849},[3832,25089,4962],{"class":3853},[3832,25091,4313],{"class":3849},[3832,25093,4140],{"class":3889},[3832,25095,19679],{"class":3849},[3832,25097,24921],{"class":3853},[3832,25099,21826],{"class":3869},[3832,25101,11249],{"class":3889},[3832,25103,4962],{"class":3853},[3832,25105,4890],{"class":3889},[3832,25107,11514],{"class":3869},[3832,25109,3857],{"class":3849},[3832,25111,24928],{"class":3853},[3832,25113,22340],{"class":3869},[3832,25115,6266],{"class":3849},[3832,25117,25118,25120,25122,25124,25126],{"class":3834,"line":4054},[3832,25119,6457],{"class":3853},[3832,25121,6274],{"class":3849},[3832,25123,6277],{"class":3869},[3832,25125,6280],{"class":3849},[3832,25127,24952],{"class":3838},[3832,25129,25130],{"class":3834,"line":4063},[3832,25131,6367],{"class":3849},[3832,25133,25134],{"class":3834,"line":4075},[3832,25135,6475],{"class":3849},[3832,25137,25138],{"class":3834,"line":4086},[3832,25139,4566],{"class":3849},[3801,25141,25142],{},[3770,25143,25144],{},"Що станеться:",[3746,25146,25147,25156],{},[3749,25148,25149,25150,25153,25154],{},"Будь-яка mutation (create\u002Fupdate\u002Fdelete) інвалідує ",[3770,25151,25152],{},"всі"," запити з тегом ",[3829,25155,6277],{},[3749,25157,25158,25159],{},"У нашому випадку — це ",[3829,25160,25161],{},"getTrips",[3801,25163,25164,25166,25167,25170,25171,25174],{},[3770,25165,5420],{}," Навіть якщо ви змінили тільки ",[3770,25168,25169],{},"одну"," поїздку (updateTrip), перезавантажується ",[3770,25172,25173],{},"весь"," список. Для великих списків це неефективно.",[3809,25176,25178],{"id":25177},"рівень-2-гранулярні-теги-за-id","Рівень 2: Гранулярні теги (за ID)",[3801,25180,25181],{},"Для більшої точності додаємо теги з ID:",[3822,25183,25185],{"className":3824,"code":25184,"language":3826,"meta":3827,"style":3827},"export const tripsApi = createApi({\n    tagTypes: ['Trip'],\n    endpoints: (builder) => ({\n        \u002F\u002F Список поїздок надає теги для кожної окремої поїздки\n        getTrips: builder.query\u003CTrip[], void>({\n            query: () => '\u002Ftrips',\n            providesTags: (result) =>\n                result\n                    ? [\n                        ...result.map((trip) => ({ type: 'Trip' as const, id: trip.id })),\n                        { type: 'Trip', id: 'LIST' },\n                    ]\n                    : [{ type: 'Trip', id: 'LIST' }],\n        }),\n        \n        \u002F\u002F Одна поїздка надає тег з конкретним ID\n        getTripById: builder.query\u003CTrip, string>({\n            query: (id) => `\u002Ftrips\u002F${id}`,\n            providesTags: (_result, _error, id) => [{ type: 'Trip', id }],\n        }),\n        \n        \u002F\u002F Оновлення інвалідує тільки конкретну поїздку\n        updateTrip: builder.mutation\u003CTrip, { id: string; title: string }>({\n            query: ({ id, ...data }) => ({ url: `\u002Ftrips\u002F${id}`, method: 'PATCH', body: data }),\n            invalidatesTags: (_result, _error, { id }) => [{ type: 'Trip', id }],\n        }),\n        \n        \u002F\u002F Видалення інвалідує поїздку + весь список\n        deleteTrip: builder.mutation\u003Cvoid, string>({\n            query: (id) => ({ url: `\u002Ftrips\u002F${id}`, method: 'DELETE' }),\n            invalidatesTags: (_result, _error, id) => [\n                { type: 'Trip', id },\n                { type: 'Trip', id: 'LIST' },\n            ],\n        }),\n        \n        \u002F\u002F Створення інвалідує тільки список (бо з'являється нова поїздка)\n        createTrip: builder.mutation\u003CTrip, CreateTripDto>({\n            query: (data) => ({ url: '\u002Ftrips', method: 'POST', body: data }),\n            invalidatesTags: [{ type: 'Trip', id: 'LIST' }],\n        }),\n    }),\n})\n",[3829,25186,25187,25201,25211,25227,25232,25252,25266,25281,25286,25291,25333,25350,25355,25373,25377,25381,25386,25407,25433,25468,25472,25476,25481,25513,25559,25593,25597,25601,25606,25626,25662,25686,25700,25716,25720,25724,25728,25733,25753,25787,25805,25809,25813],{"__ignoreMap":3827},[3832,25188,25189,25191,25193,25195,25197,25199],{"class":3834,"line":3835},[3832,25190,4105],{"class":3845},[3832,25192,4108],{"class":3889},[3832,25194,6231],{"class":4042},[3832,25196,4114],{"class":3849},[3832,25198,6153],{"class":4117},[3832,25200,4267],{"class":3849},[3832,25202,25203,25205,25207,25209],{"class":3834,"line":3842},[3832,25204,6271],{"class":3853},[3832,25206,6274],{"class":3849},[3832,25208,6277],{"class":3869},[3832,25210,11605],{"class":3849},[3832,25212,25213,25215,25217,25219,25221,25223,25225],{"class":3834,"line":3873},[3832,25214,6288],{"class":4117},[3832,25216,4304],{"class":3853},[3832,25218,4307],{"class":3849},[3832,25220,4310],{"class":3853},[3832,25222,4313],{"class":3849},[3832,25224,4140],{"class":3889},[3832,25226,6301],{"class":3849},[3832,25228,25229],{"class":3834,"line":3880},[3832,25230,25231],{"class":3838},"        \u002F\u002F Список поїздок надає теги для кожної окремої поїздки\n",[3832,25233,25234,25236,25238,25240,25242,25244,25246,25248,25250],{"class":3834,"line":3886},[3832,25235,6311],{"class":3853},[3832,25237,6314],{"class":3853},[3832,25239,4183],{"class":3849},[3832,25241,6319],{"class":4117},[3832,25243,5084],{"class":3849},[3832,25245,3977],{"class":3893},[3832,25247,6326],{"class":3849},[3832,25249,6329],{"class":3893},[3832,25251,6332],{"class":3849},[3832,25253,25254,25256,25258,25260,25262,25264],{"class":3834,"line":3900},[3832,25255,6337],{"class":4117},[3832,25257,4304],{"class":3853},[3832,25259,4137],{"class":3849},[3832,25261,4140],{"class":3889},[3832,25263,6346],{"class":3869},[3832,25265,4072],{"class":3849},[3832,25267,25268,25271,25273,25275,25277,25279],{"class":3834,"line":3912},[3832,25269,25270],{"class":4117},"            providesTags",[3832,25272,4304],{"class":3853},[3832,25274,4307],{"class":3849},[3832,25276,13782],{"class":3853},[3832,25278,4313],{"class":3849},[3832,25280,9607],{"class":3889},[3832,25282,25283],{"class":3834,"line":3922},[3832,25284,25285],{"class":3853},"                result\n",[3832,25287,25288],{"class":3834,"line":3932},[3832,25289,25290],{"class":3849},"                    ? [\n",[3832,25292,25293,25296,25298,25300,25302,25304,25306,25308,25310,25312,25314,25316,25318,25320,25322,25324,25326,25328,25330],{"class":3834,"line":3942},[3832,25294,25295],{"class":3849},"                        ...",[3832,25297,13782],{"class":3853},[3832,25299,4183],{"class":3849},[3832,25301,17783],{"class":4117},[3832,25303,4753],{"class":3849},[3832,25305,8412],{"class":3853},[3832,25307,4313],{"class":3849},[3832,25309,4140],{"class":3889},[3832,25311,19679],{"class":3849},[3832,25313,21896],{"class":3853},[3832,25315,21899],{"class":3869},[3832,25317,14013],{"class":3845},[3832,25319,4108],{"class":3889},[3832,25321,3857],{"class":3849},[3832,25323,22383],{"class":3853},[3832,25325,17136],{"class":3853},[3832,25327,4183],{"class":3849},[3832,25329,4962],{"class":3853},[3832,25331,25332],{"class":3849}," })),\n",[3832,25334,25335,25338,25340,25342,25344,25346,25348],{"class":3834,"line":3948},[3832,25336,25337],{"class":3849},"                        { ",[3832,25339,21896],{"class":3853},[3832,25341,21899],{"class":3869},[3832,25343,3857],{"class":3849},[3832,25345,22383],{"class":3853},[3832,25347,22402],{"class":3869},[3832,25349,5145],{"class":3849},[3832,25351,25352],{"class":3834,"line":3953},[3832,25353,25354],{"class":3849},"                    ]\n",[3832,25356,25357,25360,25362,25364,25366,25368,25370],{"class":3834,"line":3959},[3832,25358,25359],{"class":3849},"                    : [{ ",[3832,25361,21896],{"class":3853},[3832,25363,21899],{"class":3869},[3832,25365,3857],{"class":3849},[3832,25367,22383],{"class":3853},[3832,25369,22402],{"class":3869},[3832,25371,25372],{"class":3849}," }],\n",[3832,25374,25375],{"class":3834,"line":3969},[3832,25376,6367],{"class":3849},[3832,25378,25379],{"class":3834,"line":3986},[3832,25380,11390],{"class":3849},[3832,25382,25383],{"class":3834,"line":4000},[3832,25384,25385],{"class":3838},"        \u002F\u002F Одна поїздка надає тег з конкретним ID\n",[3832,25387,25388,25391,25393,25395,25397,25399,25401,25403,25405],{"class":3834,"line":4020},[3832,25389,25390],{"class":3853},"        getTripById:",[3832,25392,6314],{"class":3853},[3832,25394,4183],{"class":3849},[3832,25396,6319],{"class":4117},[3832,25398,5084],{"class":3849},[3832,25400,3977],{"class":3893},[3832,25402,3857],{"class":3849},[3832,25404,4008],{"class":3893},[3832,25406,6332],{"class":3849},[3832,25408,25409,25411,25413,25415,25417,25419,25421,25423,25425,25427,25429,25431],{"class":3834,"line":4025},[3832,25410,6337],{"class":4117},[3832,25412,4304],{"class":3853},[3832,25414,4307],{"class":3849},[3832,25416,4962],{"class":3853},[3832,25418,4313],{"class":3849},[3832,25420,4140],{"class":3889},[3832,25422,21826],{"class":3869},[3832,25424,11249],{"class":3889},[3832,25426,4962],{"class":3853},[3832,25428,4890],{"class":3889},[3832,25430,11514],{"class":3869},[3832,25432,4072],{"class":3849},[3832,25434,25435,25437,25439,25441,25443,25445,25447,25449,25451,25453,25455,25458,25460,25462,25464,25466],{"class":3834,"line":4030},[3832,25436,25270],{"class":4117},[3832,25438,4304],{"class":3853},[3832,25440,4307],{"class":3849},[3832,25442,21873],{"class":3853},[3832,25444,3857],{"class":3849},[3832,25446,21878],{"class":3853},[3832,25448,3857],{"class":3849},[3832,25450,4962],{"class":3853},[3832,25452,4313],{"class":3849},[3832,25454,4140],{"class":3889},[3832,25456,25457],{"class":3849}," [{ ",[3832,25459,21896],{"class":3853},[3832,25461,21899],{"class":3869},[3832,25463,3857],{"class":3849},[3832,25465,4962],{"class":3853},[3832,25467,25372],{"class":3849},[3832,25469,25470],{"class":3834,"line":4036},[3832,25471,6367],{"class":3849},[3832,25473,25474],{"class":3834,"line":4054},[3832,25475,11390],{"class":3849},[3832,25477,25478],{"class":3834,"line":4063},[3832,25479,25480],{"class":3838},"        \u002F\u002F Оновлення інвалідує тільки конкретну поїздку\n",[3832,25482,25483,25485,25487,25489,25491,25493,25495,25497,25499,25501,25503,25505,25507,25509,25511],{"class":3834,"line":4075},[3832,25484,21780],{"class":3853},[3832,25486,6314],{"class":3853},[3832,25488,4183],{"class":3849},[3832,25490,6384],{"class":4117},[3832,25492,5084],{"class":3849},[3832,25494,3977],{"class":3893},[3832,25496,4611],{"class":3849},[3832,25498,4962],{"class":3853},[3832,25500,3906],{"class":3849},[3832,25502,4008],{"class":3893},[3832,25504,12378],{"class":3849},[3832,25506,4998],{"class":3853},[3832,25508,3906],{"class":3849},[3832,25510,4008],{"class":3893},[3832,25512,24993],{"class":3849},[3832,25514,25515,25517,25519,25521,25523,25525,25527,25529,25531,25533,25535,25537,25539,25541,25543,25545,25547,25549,25551,25553,25555,25557],{"class":3834,"line":4086},[3832,25516,6337],{"class":4117},[3832,25518,4304],{"class":3853},[3832,25520,19679],{"class":3849},[3832,25522,4962],{"class":3853},[3832,25524,21810],{"class":3849},[3832,25526,6565],{"class":3853},[3832,25528,4981],{"class":3849},[3832,25530,4140],{"class":3889},[3832,25532,19679],{"class":3849},[3832,25534,24921],{"class":3853},[3832,25536,21826],{"class":3869},[3832,25538,11249],{"class":3889},[3832,25540,4962],{"class":3853},[3832,25542,4890],{"class":3889},[3832,25544,11514],{"class":3869},[3832,25546,3857],{"class":3849},[3832,25548,24928],{"class":3853},[3832,25550,21843],{"class":3869},[3832,25552,3857],{"class":3849},[3832,25554,24935],{"class":3853},[3832,25556,18279],{"class":3853},[3832,25558,6266],{"class":3849},[3832,25560,25561,25563,25565,25567,25569,25571,25573,25575,25577,25579,25581,25583,25585,25587,25589,25591],{"class":3834,"line":4091},[3832,25562,21866],{"class":4117},[3832,25564,4304],{"class":3853},[3832,25566,4307],{"class":3849},[3832,25568,21873],{"class":3853},[3832,25570,3857],{"class":3849},[3832,25572,21878],{"class":3853},[3832,25574,4611],{"class":3849},[3832,25576,4962],{"class":3853},[3832,25578,4981],{"class":3849},[3832,25580,4140],{"class":3889},[3832,25582,25457],{"class":3849},[3832,25584,21896],{"class":3853},[3832,25586,21899],{"class":3869},[3832,25588,3857],{"class":3849},[3832,25590,4962],{"class":3853},[3832,25592,25372],{"class":3849},[3832,25594,25595],{"class":3834,"line":4096},[3832,25596,6367],{"class":3849},[3832,25598,25599],{"class":3834,"line":4102},[3832,25600,11390],{"class":3849},[3832,25602,25603],{"class":3834,"line":4123},[3832,25604,25605],{"class":3838},"        \u002F\u002F Видалення інвалідує поїздку + весь список\n",[3832,25607,25608,25610,25612,25614,25616,25618,25620,25622,25624],{"class":3834,"line":4131},[3832,25609,22280],{"class":3853},[3832,25611,6314],{"class":3853},[3832,25613,4183],{"class":3849},[3832,25615,6384],{"class":4117},[3832,25617,5084],{"class":3849},[3832,25619,6329],{"class":3893},[3832,25621,3857],{"class":3849},[3832,25623,4008],{"class":3893},[3832,25625,6332],{"class":3849},[3832,25627,25628,25630,25632,25634,25636,25638,25640,25642,25644,25646,25648,25650,25652,25654,25656,25658,25660],{"class":3834,"line":4145},[3832,25629,6337],{"class":4117},[3832,25631,4304],{"class":3853},[3832,25633,4307],{"class":3849},[3832,25635,4962],{"class":3853},[3832,25637,4313],{"class":3849},[3832,25639,4140],{"class":3889},[3832,25641,19679],{"class":3849},[3832,25643,24921],{"class":3853},[3832,25645,21826],{"class":3869},[3832,25647,11249],{"class":3889},[3832,25649,4962],{"class":3853},[3832,25651,4890],{"class":3889},[3832,25653,11514],{"class":3869},[3832,25655,3857],{"class":3849},[3832,25657,24928],{"class":3853},[3832,25659,22340],{"class":3869},[3832,25661,6266],{"class":3849},[3832,25663,25664,25666,25668,25670,25672,25674,25676,25678,25680,25682,25684],{"class":3834,"line":4171},[3832,25665,21866],{"class":4117},[3832,25667,4304],{"class":3853},[3832,25669,4307],{"class":3849},[3832,25671,21873],{"class":3853},[3832,25673,3857],{"class":3849},[3832,25675,21878],{"class":3853},[3832,25677,3857],{"class":3849},[3832,25679,4962],{"class":3853},[3832,25681,4313],{"class":3849},[3832,25683,4140],{"class":3889},[3832,25685,21134],{"class":3849},[3832,25687,25688,25690,25692,25694,25696,25698],{"class":3834,"line":4192},[3832,25689,21893],{"class":3849},[3832,25691,21896],{"class":3853},[3832,25693,21899],{"class":3869},[3832,25695,3857],{"class":3849},[3832,25697,4962],{"class":3853},[3832,25699,5145],{"class":3849},[3832,25701,25702,25704,25706,25708,25710,25712,25714],{"class":3834,"line":4211},[3832,25703,21893],{"class":3849},[3832,25705,21896],{"class":3853},[3832,25707,21899],{"class":3869},[3832,25709,3857],{"class":3849},[3832,25711,22383],{"class":3853},[3832,25713,22402],{"class":3869},[3832,25715,5145],{"class":3849},[3832,25717,25718],{"class":3834,"line":4217},[3832,25719,21914],{"class":3849},[3832,25721,25722],{"class":3834,"line":4233},[3832,25723,6367],{"class":3849},[3832,25725,25726],{"class":3834,"line":4239},[3832,25727,11390],{"class":3849},[3832,25729,25730],{"class":3834,"line":4244},[3832,25731,25732],{"class":3838},"        \u002F\u002F Створення інвалідує тільки список (бо з'являється нова поїздка)\n",[3832,25734,25735,25737,25739,25741,25743,25745,25747,25749,25751],{"class":3834,"line":4249},[3832,25736,6377],{"class":3853},[3832,25738,6314],{"class":3853},[3832,25740,4183],{"class":3849},[3832,25742,6384],{"class":4117},[3832,25744,5084],{"class":3849},[3832,25746,3977],{"class":3893},[3832,25748,3857],{"class":3849},[3832,25750,20142],{"class":3893},[3832,25752,6332],{"class":3849},[3832,25754,25755,25757,25759,25761,25763,25765,25767,25769,25771,25773,25775,25777,25779,25781,25783,25785],{"class":3834,"line":4255},[3832,25756,6337],{"class":4117},[3832,25758,4304],{"class":3853},[3832,25760,4307],{"class":3849},[3832,25762,6565],{"class":3853},[3832,25764,4313],{"class":3849},[3832,25766,4140],{"class":3889},[3832,25768,19679],{"class":3849},[3832,25770,24921],{"class":3853},[3832,25772,6346],{"class":3869},[3832,25774,3857],{"class":3849},[3832,25776,24928],{"class":3853},[3832,25778,5125],{"class":3869},[3832,25780,3857],{"class":3849},[3832,25782,24935],{"class":3853},[3832,25784,18279],{"class":3853},[3832,25786,6266],{"class":3849},[3832,25788,25789,25791,25793,25795,25797,25799,25801,25803],{"class":3834,"line":4270},[3832,25790,6457],{"class":3853},[3832,25792,25457],{"class":3849},[3832,25794,21896],{"class":3853},[3832,25796,21899],{"class":3869},[3832,25798,3857],{"class":3849},[3832,25800,22383],{"class":3853},[3832,25802,22402],{"class":3869},[3832,25804,25372],{"class":3849},[3832,25806,25807],{"class":3834,"line":4281},[3832,25808,6367],{"class":3849},[3832,25810,25811],{"class":3834,"line":4289},[3832,25812,6475],{"class":3849},[3832,25814,25815],{"class":3834,"line":4298},[3832,25816,4566],{"class":3849},[3801,25818,25819],{},[3770,25820,25821],{},"Розберемо детально:",[8777,25823,25824,26048,26142,26246],{},[8780,25825,25828,25932,25937,26019,26022],{"icon":25826,"label":25827},"i-lucide-list","📋 providesTags для списку getTrips",[3822,25829,25831],{"className":3824,"code":25830,"language":3826,"meta":3827,"style":3827},"providesTags: (result) =>\n    result\n        ? [\n            ...result.map((trip) => ({ type: 'Trip', id: trip.id })),\n            { type: 'Trip', id: 'LIST' },\n        ]\n        : [{ type: 'Trip', id: 'LIST' }]\n",[3829,25832,25833,25845,25850,25855,25892,25909,25914],{"__ignoreMap":3827},[3832,25834,25835,25837,25839,25841,25843],{"class":3834,"line":3835},[3832,25836,12059],{"class":5204},[3832,25838,5208],{"class":3849},[3832,25840,13782],{"class":3853},[3832,25842,4313],{"class":3849},[3832,25844,9607],{"class":3889},[3832,25846,25847],{"class":3834,"line":3842},[3832,25848,25849],{"class":3853},"    result\n",[3832,25851,25852],{"class":3834,"line":3873},[3832,25853,25854],{"class":3849},"        ? [\n",[3832,25856,25857,25860,25862,25864,25866,25868,25870,25872,25874,25876,25878,25880,25882,25884,25886,25888,25890],{"class":3834,"line":3880},[3832,25858,25859],{"class":3849},"            ...",[3832,25861,13782],{"class":3853},[3832,25863,4183],{"class":3849},[3832,25865,17783],{"class":4117},[3832,25867,4753],{"class":3849},[3832,25869,8412],{"class":3853},[3832,25871,4313],{"class":3849},[3832,25873,4140],{"class":3889},[3832,25875,19679],{"class":3849},[3832,25877,21896],{"class":3853},[3832,25879,21899],{"class":3869},[3832,25881,3857],{"class":3849},[3832,25883,22383],{"class":3853},[3832,25885,17136],{"class":3853},[3832,25887,4183],{"class":3849},[3832,25889,4962],{"class":3853},[3832,25891,25332],{"class":3849},[3832,25893,25894,25897,25899,25901,25903,25905,25907],{"class":3834,"line":3886},[3832,25895,25896],{"class":3849},"            { ",[3832,25898,21896],{"class":3853},[3832,25900,21899],{"class":3869},[3832,25902,3857],{"class":3849},[3832,25904,22383],{"class":3853},[3832,25906,22402],{"class":3869},[3832,25908,5145],{"class":3849},[3832,25910,25911],{"class":3834,"line":3900},[3832,25912,25913],{"class":3849},"        ]\n",[3832,25915,25916,25919,25921,25923,25925,25927,25929],{"class":3834,"line":3912},[3832,25917,25918],{"class":3849},"        : [{ ",[3832,25920,21896],{"class":3853},[3832,25922,21899],{"class":3869},[3832,25924,3857],{"class":3849},[3832,25926,22383],{"class":3853},[3832,25928,22402],{"class":3869},[3832,25930,25931],{"class":3849}," }]\n",[3801,25933,25934],{},[3770,25935,25936],{},"Що генерується (приклад):",[3822,25938,25940],{"className":3824,"code":25939,"language":3826,"meta":3827,"style":3827},"[\n    { type: 'Trip', id: '1' },\n    { type: 'Trip', id: '2' },\n    { type: 'Trip', id: '3' },\n    { type: 'Trip', id: 'LIST' },\n]\n",[3829,25941,25942,25947,25965,25982,25999,26015],{"__ignoreMap":3827},[3832,25943,25944],{"class":3834,"line":3835},[3832,25945,25946],{"class":3849},"[\n",[3832,25948,25949,25952,25954,25956,25958,25960,25963],{"class":3834,"line":3842},[3832,25950,25951],{"class":3849},"    { ",[3832,25953,21896],{"class":3853},[3832,25955,21899],{"class":3869},[3832,25957,3857],{"class":3849},[3832,25959,22383],{"class":3853},[3832,25961,25962],{"class":3869}," '1'",[3832,25964,5145],{"class":3849},[3832,25966,25967,25969,25971,25973,25975,25977,25980],{"class":3834,"line":3873},[3832,25968,25951],{"class":3849},[3832,25970,21896],{"class":3853},[3832,25972,21899],{"class":3869},[3832,25974,3857],{"class":3849},[3832,25976,22383],{"class":3853},[3832,25978,25979],{"class":3869}," '2'",[3832,25981,5145],{"class":3849},[3832,25983,25984,25986,25988,25990,25992,25994,25997],{"class":3834,"line":3880},[3832,25985,25951],{"class":3849},[3832,25987,21896],{"class":3853},[3832,25989,21899],{"class":3869},[3832,25991,3857],{"class":3849},[3832,25993,22383],{"class":3853},[3832,25995,25996],{"class":3869}," '3'",[3832,25998,5145],{"class":3849},[3832,26000,26001,26003,26005,26007,26009,26011,26013],{"class":3834,"line":3886},[3832,26002,25951],{"class":3849},[3832,26004,21896],{"class":3853},[3832,26006,21899],{"class":3869},[3832,26008,3857],{"class":3849},[3832,26010,22383],{"class":3853},[3832,26012,22402],{"class":3869},[3832,26014,5145],{"class":3849},[3832,26016,26017],{"class":3834,"line":3900},[3832,26018,12098],{"class":3849},[3801,26020,26021],{},"Це означає:",[3746,26023,26024,26040],{},[3749,26025,26026,26027,26030,26031,3857,26034,3857,26037],{},"Список ",[3770,26028,26029],{},"залежить"," від поїздок з ID ",[3829,26032,26033],{},"'1'",[3829,26035,26036],{},"'2'",[3829,26038,26039],{},"'3'",[3749,26041,26026,26042,26044,26045],{},[3770,26043,26029],{}," від спеціального тегу ",[3829,26046,26047],{},"'LIST'",[8780,26049,26051,26088,26096,26100,26132],{"icon":6755,"label":26050},"🔄 invalidatesTags при оновленні (updateTrip)",[3822,26052,26054],{"className":3824,"code":26053,"language":3826,"meta":3827,"style":3827},"invalidatesTags: (_result, _error, { id }) => [{ type: 'Trip', id }]\n",[3829,26055,26056],{"__ignoreMap":3827},[3832,26057,26058,26060,26062,26064,26066,26068,26070,26072,26074,26076,26078,26080,26082,26084,26086],{"class":3834,"line":3835},[3832,26059,12068],{"class":5204},[3832,26061,5208],{"class":3849},[3832,26063,21873],{"class":3853},[3832,26065,3857],{"class":3849},[3832,26067,21878],{"class":3853},[3832,26069,4611],{"class":3849},[3832,26071,4962],{"class":3853},[3832,26073,4981],{"class":3849},[3832,26075,4140],{"class":3889},[3832,26077,25457],{"class":3849},[3832,26079,21896],{"class":3853},[3832,26081,21899],{"class":3869},[3832,26083,3857],{"class":3849},[3832,26085,4962],{"class":3853},[3832,26087,25931],{"class":3849},[3801,26089,26090,26093,26094],{},[3770,26091,26092],{},"Сценарій:"," Користувач змінює назву поїздки з ID ",[3829,26095,26036],{},[3801,26097,26098],{},[3770,26099,25144],{},[12048,26101,26102,26108],{},[3749,26103,26104,26105],{},"Інвалідується тільки тег ",[3829,26106,26107],{},"{ type: 'Trip', id: '2' }",[3749,26109,26110,26111],{},"RTK Query шукає запити з цим тегом:\n",[3746,26112,26113,26121],{},[3749,26114,26115,26118,26119],{},[3829,26116,26117],{},"getTripById('2')"," — якщо відкритий екран деталей → ",[3770,26120,18336],{},[3749,26122,26123,26126,26127,26129,26130],{},[3829,26124,26125],{},"getTrips()"," — містить ",[3829,26128,26107],{}," у тегах → ",[3770,26131,18336],{},[3801,26133,26134,7651,26136,26138,26139,26141],{},[3770,26135,9171],{},[3829,26137,25161],{}," оновиться, бо він \"підписаний\" на зміни поїздки ",[3829,26140,26036],{},"!",[8780,26143,26146,26207,26214,26218,26233,26238],{"icon":26144,"label":26145},"i-lucide-trash-2","🗑️ invalidatesTags при видаленні (deleteTrip)",[3822,26147,26149],{"className":3824,"code":26148,"language":3826,"meta":3827,"style":3827},"invalidatesTags: (_result, _error, id) => [\n    { type: 'Trip', id },\n    { type: 'Trip', id: 'LIST' },\n]\n",[3829,26150,26151,26173,26187,26203],{"__ignoreMap":3827},[3832,26152,26153,26155,26157,26159,26161,26163,26165,26167,26169,26171],{"class":3834,"line":3835},[3832,26154,12068],{"class":5204},[3832,26156,5208],{"class":3849},[3832,26158,21873],{"class":3853},[3832,26160,3857],{"class":3849},[3832,26162,21878],{"class":3853},[3832,26164,3857],{"class":3849},[3832,26166,4962],{"class":3853},[3832,26168,4313],{"class":3849},[3832,26170,4140],{"class":3889},[3832,26172,21134],{"class":3849},[3832,26174,26175,26177,26179,26181,26183,26185],{"class":3834,"line":3842},[3832,26176,25951],{"class":3849},[3832,26178,21896],{"class":3853},[3832,26180,21899],{"class":3869},[3832,26182,3857],{"class":3849},[3832,26184,4962],{"class":3853},[3832,26186,5145],{"class":3849},[3832,26188,26189,26191,26193,26195,26197,26199,26201],{"class":3834,"line":3873},[3832,26190,25951],{"class":3849},[3832,26192,21896],{"class":3853},[3832,26194,21899],{"class":3869},[3832,26196,3857],{"class":3849},[3832,26198,22383],{"class":3853},[3832,26200,22402],{"class":3869},[3832,26202,5145],{"class":3849},[3832,26204,26205],{"class":3834,"line":3880},[3832,26206,12098],{"class":3849},[3801,26208,26209,26211,26212],{},[3770,26210,26092],{}," Користувач видаляє поїздку з ID ",[3829,26213,26039],{},[3801,26215,26216],{},[3770,26217,25144],{},[12048,26219,26220,26227],{},[3749,26221,26222,26223,26226],{},"Інвалідується ",[3829,26224,26225],{},"{ type: 'Trip', id: '3' }"," — закриє екран деталей, якщо він відкритий",[3749,26228,26222,26229,26232],{},[3829,26230,26231],{},"{ type: 'Trip', id: 'LIST' }"," — оновить список (бо кількість змінилась)",[3801,26234,26235],{},[3770,26236,26237],{},"Чому два теги?",[3746,26239,26240,26243],{},[3749,26241,26242],{},"Перший — для екрана деталей конкретної поїздки",[3749,26244,26245],{},"Другий — для списку (щоб видалена поїздка зникла з UI)",[8780,26247,26250,26274,26279,26283,26298,26303],{"icon":26248,"label":26249},"i-lucide-plus","➕ invalidatesTags при створенні (createTrip)",[3822,26251,26253],{"className":3824,"code":26252,"language":3826,"meta":3827,"style":3827},"invalidatesTags: [{ type: 'Trip', id: 'LIST' }]\n",[3829,26254,26255],{"__ignoreMap":3827},[3832,26256,26257,26259,26262,26264,26266,26268,26270,26272],{"class":3834,"line":3835},[3832,26258,12068],{"class":5204},[3832,26260,26261],{"class":3849},": [{ ",[3832,26263,21896],{"class":3853},[3832,26265,21899],{"class":3869},[3832,26267,3857],{"class":3849},[3832,26269,22383],{"class":3853},[3832,26271,22402],{"class":3869},[3832,26273,25931],{"class":3849},[3801,26275,26276,26278],{},[3770,26277,26092],{}," Користувач створює нову поїздку",[3801,26280,26281],{},[3770,26282,25144],{},[12048,26284,26285,26289],{},[3749,26286,26222,26287],{},[3829,26288,26231],{},[3749,26290,26291,26292,3857,26294,26297],{},"Усі списки (",[3829,26293,25161],{},[3829,26295,26296],{},"getFilteredTrips"," тощо) оновляться",[3801,26299,26300],{},[3770,26301,26302],{},"Чому тільки 'LIST'?",[3746,26304,26305,26308],{},[3749,26306,26307],{},"Нова поїздка ще не має конкретного тегу (ми не знаємо її ID до створення)",[3749,26309,26310,26311],{},"Але ми точно знаємо, що список змінився → інвалідуємо ",[3829,26312,26047],{},[3809,26314,26316],{"id":26315},"візуалізація-як-працює-гранулярна-інвалідація","Візуалізація: Як працює гранулярна інвалідація",[8090,26318,26320],{"alt":26319},"Гранулярна система тегів",[3822,26321,26323],{"className":8095,"code":26322,"language":8097,"meta":3827,"style":3827},"@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\nskinparam defaultFontName \"Helvetica\"\n\npackage \"Cache після getTrips()\" {\n    card \"getTrips()\" as List #DCFCE7 {\n        [data: Trip[]]\n        [tags:]\n        [{ type: 'Trip', id: '1' }]\n        [{ type: 'Trip', id: '2' }]\n        [{ type: 'Trip', id: '3' }]\n        [{ type: 'Trip', id: 'LIST' }]\n    }\n}\n\npackage \"Cache після getTripById('2')\" {\n    card \"getTripById('2')\" as Detail #DBEAFE {\n        [data: Trip]\n        [tags:]\n        [{ type: 'Trip', id: '2' }]\n    }\n}\n\npackage \"Mutation: updateTrip({ id: '2', title: 'Нова назва' })\" as Update #FED7AA {\n    [invalidatesTags:]\n    [{ type: 'Trip', id: '2' }]\n}\n\nUpdate --> List : Перевіряє теги\\nЗнайдено { type: 'Trip', id: '2' }\\n→ REFETCH\nUpdate --> Detail : Перевіряє теги\\nЗнайдено { type: 'Trip', id: '2' }\\n→ REFETCH\n\nnote right of Update #FEF3C7\n    Тільки запити з тегом\n    { type: 'Trip', id: '2' }\n    будуть оновлені.\n    \n    Інші поїздки ('1', '3')\n    не будуть перезавантажені!\nend note\n\n@enduml\n",[3829,26324,26325,26329,26333,26337,26341,26345,26350,26355,26360,26365,26370,26375,26380,26385,26389,26393,26397,26402,26407,26412,26416,26420,26424,26428,26432,26437,26442,26447,26451,26455,26460,26465,26469,26474,26479,26484,26489,26493,26498,26503,26507,26511],{"__ignoreMap":3827},[3832,26326,26327],{"class":3834,"line":3835},[3832,26328,8104],{},[3832,26330,26331],{"class":3834,"line":3842},[3832,26332,8109],{},[3832,26334,26335],{"class":3834,"line":3873},[3832,26336,8114],{},[3832,26338,26339],{"class":3834,"line":3880},[3832,26340,8119],{},[3832,26342,26343],{"class":3834,"line":3886},[3832,26344,3877],{"emptyLinePlaceholder":3876},[3832,26346,26347],{"class":3834,"line":3900},[3832,26348,26349],{},"package \"Cache після getTrips()\" {\n",[3832,26351,26352],{"class":3834,"line":3912},[3832,26353,26354],{},"    card \"getTrips()\" as List #DCFCE7 {\n",[3832,26356,26357],{"class":3834,"line":3922},[3832,26358,26359],{},"        [data: Trip[]]\n",[3832,26361,26362],{"class":3834,"line":3932},[3832,26363,26364],{},"        [tags:]\n",[3832,26366,26367],{"class":3834,"line":3942},[3832,26368,26369],{},"        [{ type: 'Trip', id: '1' }]\n",[3832,26371,26372],{"class":3834,"line":3948},[3832,26373,26374],{},"        [{ type: 'Trip', id: '2' }]\n",[3832,26376,26377],{"class":3834,"line":3953},[3832,26378,26379],{},"        [{ type: 'Trip', id: '3' }]\n",[3832,26381,26382],{"class":3834,"line":3959},[3832,26383,26384],{},"        [{ type: 'Trip', id: 'LIST' }]\n",[3832,26386,26387],{"class":3834,"line":3969},[3832,26388,4236],{},[3832,26390,26391],{"class":3834,"line":3986},[3832,26392,3945],{},[3832,26394,26395],{"class":3834,"line":4000},[3832,26396,3877],{"emptyLinePlaceholder":3876},[3832,26398,26399],{"class":3834,"line":4020},[3832,26400,26401],{},"package \"Cache після getTripById('2')\" {\n",[3832,26403,26404],{"class":3834,"line":4025},[3832,26405,26406],{},"    card \"getTripById('2')\" as Detail #DBEAFE {\n",[3832,26408,26409],{"class":3834,"line":4030},[3832,26410,26411],{},"        [data: Trip]\n",[3832,26413,26414],{"class":3834,"line":4036},[3832,26415,26364],{},[3832,26417,26418],{"class":3834,"line":4054},[3832,26419,26374],{},[3832,26421,26422],{"class":3834,"line":4063},[3832,26423,4236],{},[3832,26425,26426],{"class":3834,"line":4075},[3832,26427,3945],{},[3832,26429,26430],{"class":3834,"line":4086},[3832,26431,3877],{"emptyLinePlaceholder":3876},[3832,26433,26434],{"class":3834,"line":4091},[3832,26435,26436],{},"package \"Mutation: updateTrip({ id: '2', title: 'Нова назва' })\" as Update #FED7AA {\n",[3832,26438,26439],{"class":3834,"line":4096},[3832,26440,26441],{},"    [invalidatesTags:]\n",[3832,26443,26444],{"class":3834,"line":4102},[3832,26445,26446],{},"    [{ type: 'Trip', id: '2' }]\n",[3832,26448,26449],{"class":3834,"line":4123},[3832,26450,3945],{},[3832,26452,26453],{"class":3834,"line":4131},[3832,26454,3877],{"emptyLinePlaceholder":3876},[3832,26456,26457],{"class":3834,"line":4145},[3832,26458,26459],{},"Update --> List : Перевіряє теги\\nЗнайдено { type: 'Trip', id: '2' }\\n→ REFETCH\n",[3832,26461,26462],{"class":3834,"line":4171},[3832,26463,26464],{},"Update --> Detail : Перевіряє теги\\nЗнайдено { type: 'Trip', id: '2' }\\n→ REFETCH\n",[3832,26466,26467],{"class":3834,"line":4192},[3832,26468,3877],{"emptyLinePlaceholder":3876},[3832,26470,26471],{"class":3834,"line":4211},[3832,26472,26473],{},"note right of Update #FEF3C7\n",[3832,26475,26476],{"class":3834,"line":4217},[3832,26477,26478],{},"    Тільки запити з тегом\n",[3832,26480,26481],{"class":3834,"line":4233},[3832,26482,26483],{},"    { type: 'Trip', id: '2' }\n",[3832,26485,26486],{"class":3834,"line":4239},[3832,26487,26488],{},"    будуть оновлені.\n",[3832,26490,26491],{"class":3834,"line":4244},[3832,26492,4724],{},[3832,26494,26495],{"class":3834,"line":4249},[3832,26496,26497],{},"    Інші поїздки ('1', '3')\n",[3832,26499,26500],{"class":3834,"line":4255},[3832,26501,26502],{},"    не будуть перезавантажені!\n",[3832,26504,26505],{"class":3834,"line":4270},[3832,26506,13425],{},[3832,26508,26509],{"class":3834,"line":4281},[3832,26510,3877],{"emptyLinePlaceholder":3876},[3832,26512,26513],{"class":3834,"line":4289},[3832,26514,8288],{},[3809,26516,26518],{"id":26517},"рівень-3-декілька-типів-тегів","Рівень 3: Декілька типів тегів",[3801,26520,26521],{},"У реальному застосунку є різні типи даних — поїздки, користувачі, коментарі тощо:",[3822,26523,26525],{"className":3824,"code":26524,"language":3826,"meta":3827,"style":3827},"export const api = createApi({\n    \u002F\u002F Реєструємо всі типи тегів\n    tagTypes: ['Trip', 'User', 'Comment'],\n    endpoints: (builder) => ({\n        \u002F\u002F Поїздки\n        getTrips: builder.query\u003CTrip[], void>({\n            query: () => '\u002Ftrips',\n            providesTags: (result) =>\n                result\n                    ? [...result.map((trip) => ({ type: 'Trip' as const, id: trip.id })), 'Trip']\n                    : ['Trip'],\n        }),\n        \n        \u002F\u002F Коментарі до поїздки\n        getTripComments: builder.query\u003CComment[], string>({\n            query: (tripId) => `\u002Ftrips\u002F${tripId}\u002Fcomments`,\n            providesTags: (_result, _error, tripId) => [\n                { type: 'Comment', id: `TRIP-${tripId}` },\n            ],\n        }),\n        \n        \u002F\u002F Додавання коментаря\n        addComment: builder.mutation\u003CComment, { tripId: string; text: string }>({\n            query: ({ tripId, text }) => ({\n                url: `\u002Ftrips\u002F${tripId}\u002Fcomments`,\n                method: 'POST',\n                body: { text },\n            }),\n            invalidatesTags: (_result, _error, { tripId }) => [\n                { type: 'Comment', id: `TRIP-${tripId}` },  \u002F\u002F Оновити коментарі цієї поїздки\n            ],\n        }),\n        \n        \u002F\u002F Видалення поїздки також видаляє її коментарі\n        deleteTrip: builder.mutation\u003Cvoid, string>({\n            query: (id) => ({ url: `\u002Ftrips\u002F${id}`, method: 'DELETE' }),\n            invalidatesTags: (_result, _error, id) => [\n                { type: 'Trip', id },\n                { type: 'Trip', id: 'LIST' },\n                { type: 'Comment', id: `TRIP-${id}` },  \u002F\u002F Очистити коментарі\n            ],\n        }),\n    }),\n})\n",[3829,26526,26527,26541,26546,26564,26580,26585,26605,26619,26633,26637,26683,26692,26696,26700,26705,26727,26754,26778,26804,26808,26812,26816,26821,26854,26874,26890,26898,26908,26912,26936,26963,26967,26971,26975,26980,27000,27036,27060,27074,27090,27117,27121,27125,27129],{"__ignoreMap":3827},[3832,26528,26529,26531,26533,26535,26537,26539],{"class":3834,"line":3835},[3832,26530,4105],{"class":3845},[3832,26532,4108],{"class":3889},[3832,26534,9277],{"class":4042},[3832,26536,4114],{"class":3849},[3832,26538,6153],{"class":4117},[3832,26540,4267],{"class":3849},[3832,26542,26543],{"class":3834,"line":3842},[3832,26544,26545],{"class":3838},"    \u002F\u002F Реєструємо всі типи тегів\n",[3832,26547,26548,26550,26552,26554,26556,26558,26560,26562],{"class":3834,"line":3873},[3832,26549,6271],{"class":3853},[3832,26551,6274],{"class":3849},[3832,26553,6277],{"class":3869},[3832,26555,3857],{"class":3849},[3832,26557,11602],{"class":3869},[3832,26559,3857],{"class":3849},[3832,26561,12095],{"class":3869},[3832,26563,11605],{"class":3849},[3832,26565,26566,26568,26570,26572,26574,26576,26578],{"class":3834,"line":3880},[3832,26567,6288],{"class":4117},[3832,26569,4304],{"class":3853},[3832,26571,4307],{"class":3849},[3832,26573,4310],{"class":3853},[3832,26575,4313],{"class":3849},[3832,26577,4140],{"class":3889},[3832,26579,6301],{"class":3849},[3832,26581,26582],{"class":3834,"line":3886},[3832,26583,26584],{"class":3838},"        \u002F\u002F Поїздки\n",[3832,26586,26587,26589,26591,26593,26595,26597,26599,26601,26603],{"class":3834,"line":3900},[3832,26588,6311],{"class":3853},[3832,26590,6314],{"class":3853},[3832,26592,4183],{"class":3849},[3832,26594,6319],{"class":4117},[3832,26596,5084],{"class":3849},[3832,26598,3977],{"class":3893},[3832,26600,6326],{"class":3849},[3832,26602,6329],{"class":3893},[3832,26604,6332],{"class":3849},[3832,26606,26607,26609,26611,26613,26615,26617],{"class":3834,"line":3912},[3832,26608,6337],{"class":4117},[3832,26610,4304],{"class":3853},[3832,26612,4137],{"class":3849},[3832,26614,4140],{"class":3889},[3832,26616,6346],{"class":3869},[3832,26618,4072],{"class":3849},[3832,26620,26621,26623,26625,26627,26629,26631],{"class":3834,"line":3922},[3832,26622,25270],{"class":4117},[3832,26624,4304],{"class":3853},[3832,26626,4307],{"class":3849},[3832,26628,13782],{"class":3853},[3832,26630,4313],{"class":3849},[3832,26632,9607],{"class":3889},[3832,26634,26635],{"class":3834,"line":3932},[3832,26636,25285],{"class":3853},[3832,26638,26639,26642,26644,26646,26648,26650,26652,26654,26656,26658,26660,26662,26664,26666,26668,26670,26672,26674,26676,26679,26681],{"class":3834,"line":3942},[3832,26640,26641],{"class":3849},"                    ? [...",[3832,26643,13782],{"class":3853},[3832,26645,4183],{"class":3849},[3832,26647,17783],{"class":4117},[3832,26649,4753],{"class":3849},[3832,26651,8412],{"class":3853},[3832,26653,4313],{"class":3849},[3832,26655,4140],{"class":3889},[3832,26657,19679],{"class":3849},[3832,26659,21896],{"class":3853},[3832,26661,21899],{"class":3869},[3832,26663,14013],{"class":3845},[3832,26665,4108],{"class":3889},[3832,26667,3857],{"class":3849},[3832,26669,22383],{"class":3853},[3832,26671,17136],{"class":3853},[3832,26673,4183],{"class":3849},[3832,26675,4962],{"class":3853},[3832,26677,26678],{"class":3849}," })), ",[3832,26680,6277],{"class":3869},[3832,26682,12098],{"class":3849},[3832,26684,26685,26688,26690],{"class":3834,"line":3948},[3832,26686,26687],{"class":3849},"                    : [",[3832,26689,6277],{"class":3869},[3832,26691,11605],{"class":3849},[3832,26693,26694],{"class":3834,"line":3953},[3832,26695,6367],{"class":3849},[3832,26697,26698],{"class":3834,"line":3959},[3832,26699,11390],{"class":3849},[3832,26701,26702],{"class":3834,"line":3969},[3832,26703,26704],{"class":3838},"        \u002F\u002F Коментарі до поїздки\n",[3832,26706,26707,26710,26712,26714,26716,26718,26721,26723,26725],{"class":3834,"line":3986},[3832,26708,26709],{"class":3853},"        getTripComments:",[3832,26711,6314],{"class":3853},[3832,26713,4183],{"class":3849},[3832,26715,6319],{"class":4117},[3832,26717,5084],{"class":3849},[3832,26719,26720],{"class":3893},"Comment",[3832,26722,6326],{"class":3849},[3832,26724,4008],{"class":3893},[3832,26726,6332],{"class":3849},[3832,26728,26729,26731,26733,26735,26737,26739,26741,26743,26745,26747,26749,26752],{"class":3834,"line":4000},[3832,26730,6337],{"class":4117},[3832,26732,4304],{"class":3853},[3832,26734,4307],{"class":3849},[3832,26736,8350],{"class":3853},[3832,26738,4313],{"class":3849},[3832,26740,4140],{"class":3889},[3832,26742,21826],{"class":3869},[3832,26744,11249],{"class":3889},[3832,26746,8350],{"class":3853},[3832,26748,4890],{"class":3889},[3832,26750,26751],{"class":3869},"\u002Fcomments`",[3832,26753,4072],{"class":3849},[3832,26755,26756,26758,26760,26762,26764,26766,26768,26770,26772,26774,26776],{"class":3834,"line":4020},[3832,26757,25270],{"class":4117},[3832,26759,4304],{"class":3853},[3832,26761,4307],{"class":3849},[3832,26763,21873],{"class":3853},[3832,26765,3857],{"class":3849},[3832,26767,21878],{"class":3853},[3832,26769,3857],{"class":3849},[3832,26771,8350],{"class":3853},[3832,26773,4313],{"class":3849},[3832,26775,4140],{"class":3889},[3832,26777,21134],{"class":3849},[3832,26779,26780,26782,26784,26787,26789,26791,26794,26796,26798,26800,26802],{"class":3834,"line":4025},[3832,26781,21893],{"class":3849},[3832,26783,21896],{"class":3853},[3832,26785,26786],{"class":3869}," 'Comment'",[3832,26788,3857],{"class":3849},[3832,26790,22383],{"class":3853},[3832,26792,26793],{"class":3869}," `TRIP-",[3832,26795,11249],{"class":3889},[3832,26797,8350],{"class":3853},[3832,26799,4890],{"class":3889},[3832,26801,11514],{"class":3869},[3832,26803,5145],{"class":3849},[3832,26805,26806],{"class":3834,"line":4030},[3832,26807,21914],{"class":3849},[3832,26809,26810],{"class":3834,"line":4036},[3832,26811,6367],{"class":3849},[3832,26813,26814],{"class":3834,"line":4054},[3832,26815,11390],{"class":3849},[3832,26817,26818],{"class":3834,"line":4063},[3832,26819,26820],{"class":3838},"        \u002F\u002F Додавання коментаря\n",[3832,26822,26823,26826,26828,26830,26832,26834,26836,26838,26840,26842,26844,26846,26848,26850,26852],{"class":3834,"line":4075},[3832,26824,26825],{"class":3853},"        addComment:",[3832,26827,6314],{"class":3853},[3832,26829,4183],{"class":3849},[3832,26831,6384],{"class":4117},[3832,26833,5084],{"class":3849},[3832,26835,26720],{"class":3893},[3832,26837,4611],{"class":3849},[3832,26839,8350],{"class":3853},[3832,26841,3906],{"class":3849},[3832,26843,4008],{"class":3893},[3832,26845,12378],{"class":3849},[3832,26847,13010],{"class":3853},[3832,26849,3906],{"class":3849},[3832,26851,4008],{"class":3893},[3832,26853,24993],{"class":3849},[3832,26855,26856,26858,26860,26862,26864,26866,26868,26870,26872],{"class":3834,"line":4086},[3832,26857,6337],{"class":4117},[3832,26859,4304],{"class":3853},[3832,26861,19679],{"class":3849},[3832,26863,8350],{"class":3853},[3832,26865,3857],{"class":3849},[3832,26867,13010],{"class":3853},[3832,26869,4981],{"class":3849},[3832,26871,4140],{"class":3889},[3832,26873,6301],{"class":3849},[3832,26875,26876,26878,26880,26882,26884,26886,26888],{"class":3834,"line":4091},[3832,26877,6424],{"class":3853},[3832,26879,21826],{"class":3869},[3832,26881,11249],{"class":3889},[3832,26883,8350],{"class":3853},[3832,26885,4890],{"class":3889},[3832,26887,26751],{"class":3869},[3832,26889,4072],{"class":3849},[3832,26891,26892,26894,26896],{"class":3834,"line":4096},[3832,26893,6433],{"class":3853},[3832,26895,5125],{"class":3869},[3832,26897,4072],{"class":3849},[3832,26899,26900,26902,26904,26906],{"class":3834,"line":4102},[3832,26901,6442],{"class":3853},[3832,26903,3850],{"class":3849},[3832,26905,13010],{"class":3853},[3832,26907,5145],{"class":3849},[3832,26909,26910],{"class":3834,"line":4123},[3832,26911,6452],{"class":3849},[3832,26913,26914,26916,26918,26920,26922,26924,26926,26928,26930,26932,26934],{"class":3834,"line":4131},[3832,26915,21866],{"class":4117},[3832,26917,4304],{"class":3853},[3832,26919,4307],{"class":3849},[3832,26921,21873],{"class":3853},[3832,26923,3857],{"class":3849},[3832,26925,21878],{"class":3853},[3832,26927,4611],{"class":3849},[3832,26929,8350],{"class":3853},[3832,26931,4981],{"class":3849},[3832,26933,4140],{"class":3889},[3832,26935,21134],{"class":3849},[3832,26937,26938,26940,26942,26944,26946,26948,26950,26952,26954,26956,26958,26960],{"class":3834,"line":4145},[3832,26939,21893],{"class":3849},[3832,26941,21896],{"class":3853},[3832,26943,26786],{"class":3869},[3832,26945,3857],{"class":3849},[3832,26947,22383],{"class":3853},[3832,26949,26793],{"class":3869},[3832,26951,11249],{"class":3889},[3832,26953,8350],{"class":3853},[3832,26955,4890],{"class":3889},[3832,26957,11514],{"class":3869},[3832,26959,21906],{"class":3849},[3832,26961,26962],{"class":3838},"\u002F\u002F Оновити коментарі цієї поїздки\n",[3832,26964,26965],{"class":3834,"line":4171},[3832,26966,21914],{"class":3849},[3832,26968,26969],{"class":3834,"line":4192},[3832,26970,6367],{"class":3849},[3832,26972,26973],{"class":3834,"line":4211},[3832,26974,11390],{"class":3849},[3832,26976,26977],{"class":3834,"line":4217},[3832,26978,26979],{"class":3838},"        \u002F\u002F Видалення поїздки також видаляє її коментарі\n",[3832,26981,26982,26984,26986,26988,26990,26992,26994,26996,26998],{"class":3834,"line":4233},[3832,26983,22280],{"class":3853},[3832,26985,6314],{"class":3853},[3832,26987,4183],{"class":3849},[3832,26989,6384],{"class":4117},[3832,26991,5084],{"class":3849},[3832,26993,6329],{"class":3893},[3832,26995,3857],{"class":3849},[3832,26997,4008],{"class":3893},[3832,26999,6332],{"class":3849},[3832,27001,27002,27004,27006,27008,27010,27012,27014,27016,27018,27020,27022,27024,27026,27028,27030,27032,27034],{"class":3834,"line":4239},[3832,27003,6337],{"class":4117},[3832,27005,4304],{"class":3853},[3832,27007,4307],{"class":3849},[3832,27009,4962],{"class":3853},[3832,27011,4313],{"class":3849},[3832,27013,4140],{"class":3889},[3832,27015,19679],{"class":3849},[3832,27017,24921],{"class":3853},[3832,27019,21826],{"class":3869},[3832,27021,11249],{"class":3889},[3832,27023,4962],{"class":3853},[3832,27025,4890],{"class":3889},[3832,27027,11514],{"class":3869},[3832,27029,3857],{"class":3849},[3832,27031,24928],{"class":3853},[3832,27033,22340],{"class":3869},[3832,27035,6266],{"class":3849},[3832,27037,27038,27040,27042,27044,27046,27048,27050,27052,27054,27056,27058],{"class":3834,"line":4244},[3832,27039,21866],{"class":4117},[3832,27041,4304],{"class":3853},[3832,27043,4307],{"class":3849},[3832,27045,21873],{"class":3853},[3832,27047,3857],{"class":3849},[3832,27049,21878],{"class":3853},[3832,27051,3857],{"class":3849},[3832,27053,4962],{"class":3853},[3832,27055,4313],{"class":3849},[3832,27057,4140],{"class":3889},[3832,27059,21134],{"class":3849},[3832,27061,27062,27064,27066,27068,27070,27072],{"class":3834,"line":4249},[3832,27063,21893],{"class":3849},[3832,27065,21896],{"class":3853},[3832,27067,21899],{"class":3869},[3832,27069,3857],{"class":3849},[3832,27071,4962],{"class":3853},[3832,27073,5145],{"class":3849},[3832,27075,27076,27078,27080,27082,27084,27086,27088],{"class":3834,"line":4255},[3832,27077,21893],{"class":3849},[3832,27079,21896],{"class":3853},[3832,27081,21899],{"class":3869},[3832,27083,3857],{"class":3849},[3832,27085,22383],{"class":3853},[3832,27087,22402],{"class":3869},[3832,27089,5145],{"class":3849},[3832,27091,27092,27094,27096,27098,27100,27102,27104,27106,27108,27110,27112,27114],{"class":3834,"line":4270},[3832,27093,21893],{"class":3849},[3832,27095,21896],{"class":3853},[3832,27097,26786],{"class":3869},[3832,27099,3857],{"class":3849},[3832,27101,22383],{"class":3853},[3832,27103,26793],{"class":3869},[3832,27105,11249],{"class":3889},[3832,27107,4962],{"class":3853},[3832,27109,4890],{"class":3889},[3832,27111,11514],{"class":3869},[3832,27113,21906],{"class":3849},[3832,27115,27116],{"class":3838},"\u002F\u002F Очистити коментарі\n",[3832,27118,27119],{"class":3834,"line":4281},[3832,27120,21914],{"class":3849},[3832,27122,27123],{"class":3834,"line":4289},[3832,27124,6367],{"class":3849},[3832,27126,27127],{"class":3834,"line":4298},[3832,27128,6475],{"class":3849},[3832,27130,27131],{"class":3834,"line":4320},[3832,27132,4566],{"class":3849},[3809,27134,27136],{"id":27135},"стратегії-тегування-коли-що-використовувати","Стратегії тегування: Коли що використовувати",[8608,27138,27139,27152],{},[8611,27140,27141],{},[8614,27142,27143,27146,27149],{},[8617,27144,27145],{"align":8619},"Сценарій",[8617,27147,27148],{"align":8619},"Стратегія",[8617,27150,27151],{"align":8619},"Приклад",[8641,27153,27154,27172,27187,27202,27217],{},[8614,27155,27156,27161,27167],{},[8646,27157,27158],{"align":8619},[3770,27159,27160],{},"Створення нової сутності",[8646,27162,27163,27164],{"align":8619},"Інвалідувати ",[3829,27165,27166],{},"LIST",[8646,27168,27169],{"align":8619},[3829,27170,27171],{},"invalidatesTags: [{ type: 'Trip', id: 'LIST' }]",[8614,27173,27174,27179,27182],{},[8646,27175,27176],{"align":8619},[3770,27177,27178],{},"Оновлення існуючої сутності",[8646,27180,27181],{"align":8619},"Інвалідувати конкретний ID",[8646,27183,27184],{"align":8619},[3829,27185,27186],{},"invalidatesTags: [{ type: 'Trip', id: tripId }]",[8614,27188,27189,27194,27197],{},[8646,27190,27191],{"align":8619},[3770,27192,27193],{},"Видалення сутності",[8646,27195,27196],{"align":8619},"Інвалідувати ID + LIST",[8646,27198,27199],{"align":8619},[3829,27200,27201],{},"invalidatesTags: [{ type: 'Trip', id: tripId }, { type: 'Trip', id: 'LIST' }]",[8614,27203,27204,27209,27212],{},[8646,27205,27206],{"align":8619},[3770,27207,27208],{},"Зміна залежних даних",[8646,27210,27211],{"align":8619},"Інвалідувати всі пов'язані типи",[8646,27213,27214],{"align":8619},[3829,27215,27216],{},"invalidatesTags: ['Trip', 'Comment', 'User']",[8614,27218,27219,27224,27227],{},[8646,27220,27221],{"align":8619},[3770,27222,27223],{},"Масове оновлення",[8646,27225,27226],{"align":8619},"Інвалідувати весь тип",[8646,27228,27229],{"align":8619},[3829,27230,6763],{},[3809,27232,27234],{"id":27233},"просунута-техніка-умовна-інвалідація","Просунута техніка: Умовна інвалідація",[3801,27236,27237],{},"Іноді потрібно інвалідувати теги тільки за певних умов:",[3822,27239,27241],{"className":3824,"code":27240,"language":3826,"meta":3827,"style":3827},"export const tripsApi = createApi({\n    endpoints: (builder) => ({\n        updateTripStatus: builder.mutation\u003CTrip, { id: string; status: 'active' | 'archived' }>({\n            query: ({ id, status }) => ({\n                url: `\u002Ftrips\u002F${id}\u002Fstatus`,\n                method: 'PATCH',\n                body: { status },\n            }),\n            invalidatesTags: (result, error, { id, status }) => {\n                const tags = [{ type: 'Trip' as const, id }]\n                \n                \u002F\u002F Якщо поїздку архівували — оновити також список активних\n                if (status === 'archived') {\n                    tags.push({ type: 'Trip', id: 'ACTIVE-LIST' })\n                }\n                \n                return tags\n            },\n        }),\n        \n        getActiveTrips: builder.query\u003CTrip[], void>({\n            query: () => '\u002Ftrips?status=active',\n            providesTags: [{ type: 'Trip', id: 'ACTIVE-LIST' }],\n        }),\n    }),\n})\n",[3829,27242,27243,27257,27273,27311,27331,27348,27356,27366,27370,27398,27422,27426,27431,27445,27469,27473,27477,27484,27488,27492,27496,27517,27532,27550,27554,27558],{"__ignoreMap":3827},[3832,27244,27245,27247,27249,27251,27253,27255],{"class":3834,"line":3835},[3832,27246,4105],{"class":3845},[3832,27248,4108],{"class":3889},[3832,27250,6231],{"class":4042},[3832,27252,4114],{"class":3849},[3832,27254,6153],{"class":4117},[3832,27256,4267],{"class":3849},[3832,27258,27259,27261,27263,27265,27267,27269,27271],{"class":3834,"line":3842},[3832,27260,6288],{"class":4117},[3832,27262,4304],{"class":3853},[3832,27264,4307],{"class":3849},[3832,27266,4310],{"class":3853},[3832,27268,4313],{"class":3849},[3832,27270,4140],{"class":3889},[3832,27272,6301],{"class":3849},[3832,27274,27275,27278,27280,27282,27284,27286,27288,27290,27292,27294,27296,27298,27300,27302,27304,27306,27309],{"class":3834,"line":3873},[3832,27276,27277],{"class":3853},"        updateTripStatus:",[3832,27279,6314],{"class":3853},[3832,27281,4183],{"class":3849},[3832,27283,6384],{"class":4117},[3832,27285,5084],{"class":3849},[3832,27287,3977],{"class":3893},[3832,27289,4611],{"class":3849},[3832,27291,4962],{"class":3853},[3832,27293,3906],{"class":3849},[3832,27295,4008],{"class":3893},[3832,27297,12378],{"class":3849},[3832,27299,13800],{"class":3853},[3832,27301,3906],{"class":3849},[3832,27303,5924],{"class":3869},[3832,27305,4011],{"class":3849},[3832,27307,27308],{"class":3869},"'archived'",[3832,27310,24993],{"class":3849},[3832,27312,27313,27315,27317,27319,27321,27323,27325,27327,27329],{"class":3834,"line":3880},[3832,27314,6337],{"class":4117},[3832,27316,4304],{"class":3853},[3832,27318,19679],{"class":3849},[3832,27320,4962],{"class":3853},[3832,27322,3857],{"class":3849},[3832,27324,13800],{"class":3853},[3832,27326,4981],{"class":3849},[3832,27328,4140],{"class":3889},[3832,27330,6301],{"class":3849},[3832,27332,27333,27335,27337,27339,27341,27343,27346],{"class":3834,"line":3886},[3832,27334,6424],{"class":3853},[3832,27336,21826],{"class":3869},[3832,27338,11249],{"class":3889},[3832,27340,4962],{"class":3853},[3832,27342,4890],{"class":3889},[3832,27344,27345],{"class":3869},"\u002Fstatus`",[3832,27347,4072],{"class":3849},[3832,27349,27350,27352,27354],{"class":3834,"line":3900},[3832,27351,6433],{"class":3853},[3832,27353,21843],{"class":3869},[3832,27355,4072],{"class":3849},[3832,27357,27358,27360,27362,27364],{"class":3834,"line":3912},[3832,27359,6442],{"class":3853},[3832,27361,3850],{"class":3849},[3832,27363,13800],{"class":3853},[3832,27365,5145],{"class":3849},[3832,27367,27368],{"class":3834,"line":3922},[3832,27369,6452],{"class":3849},[3832,27371,27372,27374,27376,27378,27380,27382,27384,27386,27388,27390,27392,27394,27396],{"class":3834,"line":3932},[3832,27373,21866],{"class":4117},[3832,27375,4304],{"class":3853},[3832,27377,4307],{"class":3849},[3832,27379,13782],{"class":3853},[3832,27381,3857],{"class":3849},[3832,27383,4386],{"class":3853},[3832,27385,4611],{"class":3849},[3832,27387,4962],{"class":3853},[3832,27389,3857],{"class":3849},[3832,27391,13800],{"class":3853},[3832,27393,4981],{"class":3849},[3832,27395,4140],{"class":3889},[3832,27397,3897],{"class":3849},[3832,27399,27400,27402,27405,27408,27410,27412,27414,27416,27418,27420],{"class":3834,"line":3942},[3832,27401,14926],{"class":3889},[3832,27403,27404],{"class":4042}," tags",[3832,27406,27407],{"class":3849}," = [{ ",[3832,27409,21896],{"class":3853},[3832,27411,21899],{"class":3869},[3832,27413,14013],{"class":3845},[3832,27415,4108],{"class":3889},[3832,27417,3857],{"class":3849},[3832,27419,4962],{"class":3853},[3832,27421,25931],{"class":3849},[3832,27423,27424],{"class":3834,"line":3948},[3832,27425,14921],{"class":3849},[3832,27427,27428],{"class":3834,"line":3953},[3832,27429,27430],{"class":3838},"                \u002F\u002F Якщо поїздку архівували — оновити також список активних\n",[3832,27432,27433,27435,27437,27439,27441,27443],{"class":3834,"line":3959},[3832,27434,15035],{"class":3845},[3832,27436,4307],{"class":3849},[3832,27438,13800],{"class":3853},[3832,27440,5921],{"class":3849},[3832,27442,27308],{"class":3869},[3832,27444,4189],{"class":3849},[3832,27446,27447,27450,27452,27454,27456,27458,27460,27462,27464,27467],{"class":3834,"line":3969},[3832,27448,27449],{"class":3853},"                    tags",[3832,27451,4183],{"class":3849},[3832,27453,5327],{"class":4117},[3832,27455,4976],{"class":3849},[3832,27457,21896],{"class":3853},[3832,27459,21899],{"class":3869},[3832,27461,3857],{"class":3849},[3832,27463,22383],{"class":3853},[3832,27465,27466],{"class":3869}," 'ACTIVE-LIST'",[3832,27468,21498],{"class":3849},[3832,27470,27471],{"class":3834,"line":3986},[3832,27472,15165],{"class":3849},[3832,27474,27475],{"class":3834,"line":4000},[3832,27476,14921],{"class":3849},[3832,27478,27479,27481],{"class":3834,"line":4020},[3832,27480,16712],{"class":3845},[3832,27482,27483],{"class":3853}," tags\n",[3832,27485,27486],{"class":3834,"line":4025},[3832,27487,13923],{"class":3849},[3832,27489,27490],{"class":3834,"line":4030},[3832,27491,6367],{"class":3849},[3832,27493,27494],{"class":3834,"line":4036},[3832,27495,11390],{"class":3849},[3832,27497,27498,27501,27503,27505,27507,27509,27511,27513,27515],{"class":3834,"line":4054},[3832,27499,27500],{"class":3853},"        getActiveTrips:",[3832,27502,6314],{"class":3853},[3832,27504,4183],{"class":3849},[3832,27506,6319],{"class":4117},[3832,27508,5084],{"class":3849},[3832,27510,3977],{"class":3893},[3832,27512,6326],{"class":3849},[3832,27514,6329],{"class":3893},[3832,27516,6332],{"class":3849},[3832,27518,27519,27521,27523,27525,27527,27530],{"class":3834,"line":4063},[3832,27520,6337],{"class":4117},[3832,27522,4304],{"class":3853},[3832,27524,4137],{"class":3849},[3832,27526,4140],{"class":3889},[3832,27528,27529],{"class":3869}," '\u002Ftrips?status=active'",[3832,27531,4072],{"class":3849},[3832,27533,27534,27536,27538,27540,27542,27544,27546,27548],{"class":3834,"line":4075},[3832,27535,6353],{"class":3853},[3832,27537,25457],{"class":3849},[3832,27539,21896],{"class":3853},[3832,27541,21899],{"class":3869},[3832,27543,3857],{"class":3849},[3832,27545,22383],{"class":3853},[3832,27547,27466],{"class":3869},[3832,27549,25372],{"class":3849},[3832,27551,27552],{"class":3834,"line":4086},[3832,27553,6367],{"class":3849},[3832,27555,27556],{"class":3834,"line":4091},[3832,27557,6475],{"class":3849},[3832,27559,27560],{"class":3834,"line":4096},[3832,27561,4566],{"class":3849},[3809,27563,27565],{"id":27564},"дебаг-як-побачити-теги-у-redux-devtools","Дебаг: Як побачити теги у Redux DevTools",[3801,27567,27568],{},"Відкрийте Redux DevTools та перейдіть у вкладку \"State\". Знайдіть свій API:",[3822,27570,27573],{"className":27571,"code":27572,"language":4227,"meta":3827,"style":3827},"language-json shiki shiki-themes light-plus dark-plus dark-plus","{\n    \"tripsApi\": {\n        \"queries\": {\n            \"getTrips(undefined)\": {\n                \"status\": \"fulfilled\",\n                \"data\": [...],\n                \"providedTags\": [\n                    { \"type\": \"Trip\", \"id\": \"1\" },\n                    { \"type\": \"Trip\", \"id\": \"2\" },\n                    { \"type\": \"Trip\", \"id\": \"LIST\" }\n                ]\n            },\n            \"getTripById(\\\"2\\\")\": {\n                \"status\": \"fulfilled\",\n                \"data\": { ... },\n                \"providedTags\": [\n                    { \"type\": \"Trip\", \"id\": \"2\" }\n                ]\n            }\n        },\n        \"mutations\": {}\n    }\n}\n",[3829,27574,27575,27579,27587,27594,27601,27613,27626,27634,27659,27680,27701,27706,27710,27729,27739,27749,27755,27775,27779,27783,27787,27795,27799],{"__ignoreMap":3827},[3832,27576,27577],{"class":3834,"line":3835},[3832,27578,11782],{"class":3849},[3832,27580,27581,27585],{"class":3834,"line":3842},[3832,27582,27584],{"class":27583},"sLwNe","    \"tripsApi\"",[3832,27586,17308],{"class":3849},[3832,27588,27589,27592],{"class":3834,"line":3873},[3832,27590,27591],{"class":27583},"        \"queries\"",[3832,27593,17308],{"class":3849},[3832,27595,27596,27599],{"class":3834,"line":3880},[3832,27597,27598],{"class":27583},"            \"getTrips(undefined)\"",[3832,27600,17308],{"class":3849},[3832,27602,27603,27606,27608,27611],{"class":3834,"line":3886},[3832,27604,27605],{"class":27583},"                \"status\"",[3832,27607,3906],{"class":3849},[3832,27609,27610],{"class":3869},"\"fulfilled\"",[3832,27612,4072],{"class":3849},[3832,27614,27615,27618,27620,27624],{"class":3834,"line":3900},[3832,27616,27617],{"class":27583},"                \"data\"",[3832,27619,12084],{"class":3849},[3832,27621,27623],{"class":27622},"se1LK","...",[3832,27625,11605],{"class":3849},[3832,27627,27628,27631],{"class":3834,"line":3912},[3832,27629,27630],{"class":27583},"                \"providedTags\"",[3832,27632,27633],{"class":3849},": [\n",[3832,27635,27636,27639,27642,27644,27647,27649,27652,27654,27657],{"class":3834,"line":3922},[3832,27637,27638],{"class":3849},"                    { ",[3832,27640,27641],{"class":27583},"\"type\"",[3832,27643,3906],{"class":3849},[3832,27645,27646],{"class":3869},"\"Trip\"",[3832,27648,3857],{"class":3849},[3832,27650,27651],{"class":27583},"\"id\"",[3832,27653,3906],{"class":3849},[3832,27655,27656],{"class":3869},"\"1\"",[3832,27658,5145],{"class":3849},[3832,27660,27661,27663,27665,27667,27669,27671,27673,27675,27678],{"class":3834,"line":3932},[3832,27662,27638],{"class":3849},[3832,27664,27641],{"class":27583},[3832,27666,3906],{"class":3849},[3832,27668,27646],{"class":3869},[3832,27670,3857],{"class":3849},[3832,27672,27651],{"class":27583},[3832,27674,3906],{"class":3849},[3832,27676,27677],{"class":3869},"\"2\"",[3832,27679,5145],{"class":3849},[3832,27681,27682,27684,27686,27688,27690,27692,27694,27696,27699],{"class":3834,"line":3942},[3832,27683,27638],{"class":3849},[3832,27685,27641],{"class":27583},[3832,27687,3906],{"class":3849},[3832,27689,27646],{"class":3869},[3832,27691,3857],{"class":3849},[3832,27693,27651],{"class":27583},[3832,27695,3906],{"class":3849},[3832,27697,27698],{"class":3869},"\"LIST\"",[3832,27700,11831],{"class":3849},[3832,27702,27703],{"class":3834,"line":3948},[3832,27704,27705],{"class":3849},"                ]\n",[3832,27707,27708],{"class":3834,"line":3953},[3832,27709,13923],{"class":3849},[3832,27711,27712,27715,27719,27722,27724,27727],{"class":3834,"line":3959},[3832,27713,27714],{"class":27583},"            \"getTripById(",[3832,27716,27718],{"class":27717},"sjcCO","\\\"",[3832,27720,27721],{"class":27583},"2",[3832,27723,27718],{"class":27717},[3832,27725,27726],{"class":27583},")\"",[3832,27728,17308],{"class":3849},[3832,27730,27731,27733,27735,27737],{"class":3834,"line":3969},[3832,27732,27605],{"class":27583},[3832,27734,3906],{"class":3849},[3832,27736,27610],{"class":3869},[3832,27738,4072],{"class":3849},[3832,27740,27741,27743,27745,27747],{"class":3834,"line":3986},[3832,27742,27617],{"class":27583},[3832,27744,11801],{"class":3849},[3832,27746,27623],{"class":27622},[3832,27748,5145],{"class":3849},[3832,27750,27751,27753],{"class":3834,"line":4000},[3832,27752,27630],{"class":27583},[3832,27754,27633],{"class":3849},[3832,27756,27757,27759,27761,27763,27765,27767,27769,27771,27773],{"class":3834,"line":4020},[3832,27758,27638],{"class":3849},[3832,27760,27641],{"class":27583},[3832,27762,3906],{"class":3849},[3832,27764,27646],{"class":3869},[3832,27766,3857],{"class":3849},[3832,27768,27651],{"class":27583},[3832,27770,3906],{"class":3849},[3832,27772,27677],{"class":3869},[3832,27774,11831],{"class":3849},[3832,27776,27777],{"class":3834,"line":4025},[3832,27778,27705],{"class":3849},[3832,27780,27781],{"class":3834,"line":4030},[3832,27782,11521],{"class":3849},[3832,27784,27785],{"class":3834,"line":4036},[3832,27786,7069],{"class":3849},[3832,27788,27789,27792],{"class":3834,"line":4054},[3832,27790,27791],{"class":27583},"        \"mutations\"",[3832,27793,27794],{"class":3849},": {}\n",[3832,27796,27797],{"class":3834,"line":4063},[3832,27798,4236],{"class":3849},[3832,27800,27801],{"class":3834,"line":4075},[3832,27802,3945],{"class":3849},[3801,27804,27805],{},"Це допоможе зрозуміти, які теги надає кожен запит!",[8569,27807,27808,27813,27825],{},[3801,27809,27810],{},[3770,27811,27812],{},"Золоте правило тегів:",[3746,27814,27815,27820],{},[3749,27816,27817,27819],{},[3829,27818,12059],{}," — \"Цей запит надає дані про...\"",[3749,27821,27822,27824],{},[3829,27823,12068],{}," — \"Ця мутація змінила дані про...\"",[3801,27826,27827],{},"Якщо вони збігаються — інвалідація спрацює автоматично!",[3793,27829],{},[3796,27831,27833],{"id":27832},"оптимістичні-оновлення-optimistic-updates-у-rtk-query","Оптимістичні оновлення (Optimistic Updates) у RTK Query",[3801,27835,27836,27837,27840,27841,5621],{},"Користувач не повинен чекати відповіді сервера при натисканні простих дій (лайк, чекбокс, додавання в закладки). Інтерфейс повинен оновлюватися ",[3770,27838,27839],{},"миттєво (0 мс затримки)",", а у випадку мережевого збою — непомітно повертатися до вихідного стану (",[3817,27842,27843],{},"Rollback",[3801,27845,27846,27847,27852,27853,4304],{},"У RTK Query це реалізується за допомогою функції ",[3770,27848,27849],{},[3829,27850,27851],{},"onQueryStarted"," та утиліти ",[3770,27854,27855],{},[3829,27856,27857],{},"updateQueryData",[3822,27859,27861],{"className":3824,"code":27860,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fservices\u002FtripsOptimisticApi.ts\nimport { baseApi } from '.\u002FbaseApi'\nimport type { Trip } from '.\u002FtripsApi'\n\nexport const tripsOptimisticApi = baseApi.injectEndpoints({\n    endpoints: (builder) => ({\n        toggleTripFavorite: builder.mutation\u003C{ success: boolean; isFavorite: boolean }, { tripId: string }>({\n            query: ({ tripId }) => ({\n                url: `\u002Ftrips\u002F${tripId}\u002Ffavorite`,\n                method: 'POST',\n            }),\n\n            \u002F\u002F Lifecycle-хук, що викликається ОДРАЗУ при запуску мутації\n            async onQueryStarted({ tripId }, { dispatch, queryFulfilled }) {\n                \u002F\u002F 1. ОПТИМІСТИЧНЕ ОНОВЛЕННЯ: прямо модифікуємо draft-кеш списку поїздок\n                const patchResult = dispatch(\n                    baseApi.util.updateQueryData('getAllTrips' as any, undefined, (draft: Trip[]) => {\n                        const trip = draft.find((t) => t.id === tripId)\n                        if (trip) {\n                            \u002F\u002F Миттєво перемикаємо прапорець у локальному кеші\n                            trip.isFavorite = !trip.isFavorite\n                        }\n                    }),\n                )\n\n                try {\n                    \u002F\u002F 2. Очікуємо на реальну відповідь бекенду\n                    await queryFulfilled\n                } catch {\n                    \u002F\u002F 3. ВІДКАТ (ROLLBACK): Якщо сервер повернув 500 або зникла мережа\n                    patchResult.undo()\n                }\n            },\n        }),\n    }),\n})\n\nexport const { useToggleTripFavoriteMutation } = tripsOptimisticApi\n",[3829,27862,27863,27868,27884,27901,27905,27925,27941,27980,27996,28013,28021,28025,28029,28034,28057,28062,28075,28116,28151,28162,28167,28186,28190,28195,28199,28203,28210,28215,28223,28231,28236,28248,28252,28256,28260,28264,28268,28272],{"__ignoreMap":3827},[3832,27864,27865],{"class":3834,"line":3835},[3832,27866,27867],{"class":3838},"\u002F\u002F src\u002Fservices\u002FtripsOptimisticApi.ts\n",[3832,27869,27870,27872,27874,27877,27879,27881],{"class":3834,"line":3842},[3832,27871,3846],{"class":3845},[3832,27873,3850],{"class":3849},[3832,27875,27876],{"class":3853},"baseApi",[3832,27878,3863],{"class":3849},[3832,27880,3866],{"class":3845},[3832,27882,27883],{"class":3869}," '.\u002FbaseApi'\n",[3832,27885,27886,27888,27890,27892,27894,27896,27898],{"class":3834,"line":3873},[3832,27887,3846],{"class":3845},[3832,27889,9673],{"class":3845},[3832,27891,3850],{"class":3849},[3832,27893,3977],{"class":3853},[3832,27895,3863],{"class":3849},[3832,27897,3866],{"class":3845},[3832,27899,27900],{"class":3869}," '.\u002FtripsApi'\n",[3832,27902,27903],{"class":3834,"line":3880},[3832,27904,3877],{"emptyLinePlaceholder":3876},[3832,27906,27907,27909,27911,27914,27916,27918,27920,27923],{"class":3834,"line":3886},[3832,27908,4105],{"class":3845},[3832,27910,4108],{"class":3889},[3832,27912,27913],{"class":4042}," tripsOptimisticApi",[3832,27915,4114],{"class":3849},[3832,27917,27876],{"class":3853},[3832,27919,4183],{"class":3849},[3832,27921,27922],{"class":4117},"injectEndpoints",[3832,27924,4267],{"class":3849},[3832,27926,27927,27929,27931,27933,27935,27937,27939],{"class":3834,"line":3900},[3832,27928,6288],{"class":4117},[3832,27930,4304],{"class":3853},[3832,27932,4307],{"class":3849},[3832,27934,4310],{"class":3853},[3832,27936,4313],{"class":3849},[3832,27938,4140],{"class":3889},[3832,27940,6301],{"class":3849},[3832,27942,27943,27946,27948,27950,27952,27954,27956,27958,27960,27962,27965,27967,27969,27972,27974,27976,27978],{"class":3834,"line":3912},[3832,27944,27945],{"class":3853},"        toggleTripFavorite:",[3832,27947,6314],{"class":3853},[3832,27949,4183],{"class":3849},[3832,27951,6384],{"class":4117},[3832,27953,12498],{"class":3849},[3832,27955,21601],{"class":3853},[3832,27957,3906],{"class":3849},[3832,27959,3994],{"class":3893},[3832,27961,12378],{"class":3849},[3832,27963,27964],{"class":3853},"isFavorite",[3832,27966,3906],{"class":3849},[3832,27968,3994],{"class":3893},[3832,27970,27971],{"class":3849}," }, { ",[3832,27973,8350],{"class":3853},[3832,27975,3906],{"class":3849},[3832,27977,4008],{"class":3893},[3832,27979,24993],{"class":3849},[3832,27981,27982,27984,27986,27988,27990,27992,27994],{"class":3834,"line":3922},[3832,27983,6337],{"class":4117},[3832,27985,4304],{"class":3853},[3832,27987,19679],{"class":3849},[3832,27989,8350],{"class":3853},[3832,27991,4981],{"class":3849},[3832,27993,4140],{"class":3889},[3832,27995,6301],{"class":3849},[3832,27997,27998,28000,28002,28004,28006,28008,28011],{"class":3834,"line":3932},[3832,27999,6424],{"class":3853},[3832,28001,21826],{"class":3869},[3832,28003,11249],{"class":3889},[3832,28005,8350],{"class":3853},[3832,28007,4890],{"class":3889},[3832,28009,28010],{"class":3869},"\u002Ffavorite`",[3832,28012,4072],{"class":3849},[3832,28014,28015,28017,28019],{"class":3834,"line":3942},[3832,28016,6433],{"class":3853},[3832,28018,5125],{"class":3869},[3832,28020,4072],{"class":3849},[3832,28022,28023],{"class":3834,"line":3948},[3832,28024,6452],{"class":3849},[3832,28026,28027],{"class":3834,"line":3953},[3832,28028,3877],{"emptyLinePlaceholder":3876},[3832,28030,28031],{"class":3834,"line":3959},[3832,28032,28033],{"class":3838},"            \u002F\u002F Lifecycle-хук, що викликається ОДРАЗУ при запуску мутації\n",[3832,28035,28036,28039,28042,28044,28046,28048,28050,28052,28055],{"class":3834,"line":3969},[3832,28037,28038],{"class":3889},"            async",[3832,28040,28041],{"class":4117}," onQueryStarted",[3832,28043,4976],{"class":3849},[3832,28045,8350],{"class":3853},[3832,28047,27971],{"class":3849},[3832,28049,4809],{"class":3853},[3832,28051,3857],{"class":3849},[3832,28053,28054],{"class":3853},"queryFulfilled",[3832,28056,8353],{"class":3849},[3832,28058,28059],{"class":3834,"line":3986},[3832,28060,28061],{"class":3838},"                \u002F\u002F 1. ОПТИМІСТИЧНЕ ОНОВЛЕННЯ: прямо модифікуємо draft-кеш списку поїздок\n",[3832,28063,28064,28066,28069,28071,28073],{"class":3834,"line":4000},[3832,28065,14926],{"class":3889},[3832,28067,28068],{"class":4042}," patchResult",[3832,28070,4114],{"class":3849},[3832,28072,4809],{"class":4117},[3832,28074,4120],{"class":3849},[3832,28076,28077,28080,28082,28084,28086,28088,28090,28093,28095,28097,28099,28101,28103,28106,28108,28110,28112,28114],{"class":3834,"line":4020},[3832,28078,28079],{"class":3853},"                    baseApi",[3832,28081,4183],{"class":3849},[3832,28083,24373],{"class":3853},[3832,28085,4183],{"class":3849},[3832,28087,27857],{"class":4117},[3832,28089,4162],{"class":3849},[3832,28091,28092],{"class":3869},"'getAllTrips'",[3832,28094,14013],{"class":3845},[3832,28096,11460],{"class":3893},[3832,28098,3857],{"class":3849},[3832,28100,16886],{"class":3889},[3832,28102,4351],{"class":3849},[3832,28104,28105],{"class":3853},"draft",[3832,28107,3906],{"class":3849},[3832,28109,3977],{"class":3893},[3832,28111,17581],{"class":3849},[3832,28113,4140],{"class":3889},[3832,28115,3897],{"class":3849},[3832,28117,28118,28121,28123,28125,28127,28129,28131,28133,28135,28137,28139,28141,28143,28145,28147,28149],{"class":3834,"line":4025},[3832,28119,28120],{"class":3889},"                        const",[3832,28122,17136],{"class":4042},[3832,28124,4114],{"class":3849},[3832,28126,28105],{"class":3853},[3832,28128,4183],{"class":3849},[3832,28130,19565],{"class":4117},[3832,28132,4753],{"class":3849},[3832,28134,19570],{"class":3853},[3832,28136,4313],{"class":3849},[3832,28138,4140],{"class":3889},[3832,28140,19575],{"class":3853},[3832,28142,4183],{"class":3849},[3832,28144,4962],{"class":3853},[3832,28146,5921],{"class":3849},[3832,28148,8350],{"class":3853},[3832,28150,4168],{"class":3849},[3832,28152,28153,28156,28158,28160],{"class":3834,"line":4030},[3832,28154,28155],{"class":3845},"                        if",[3832,28157,4307],{"class":3849},[3832,28159,8412],{"class":3853},[3832,28161,4189],{"class":3849},[3832,28163,28164],{"class":3834,"line":4036},[3832,28165,28166],{"class":3838},"                            \u002F\u002F Миттєво перемикаємо прапорець у локальному кеші\n",[3832,28168,28169,28172,28174,28176,28179,28181,28183],{"class":3834,"line":4054},[3832,28170,28171],{"class":3853},"                            trip",[3832,28173,4183],{"class":3849},[3832,28175,27964],{"class":3853},[3832,28177,28178],{"class":3849}," = !",[3832,28180,8412],{"class":3853},[3832,28182,4183],{"class":3849},[3832,28184,28185],{"class":3853},"isFavorite\n",[3832,28187,28188],{"class":3834,"line":4063},[3832,28189,9050],{"class":3849},[3832,28191,28192],{"class":3834,"line":4075},[3832,28193,28194],{"class":3849},"                    }),\n",[3832,28196,28197],{"class":3834,"line":4086},[3832,28198,15026],{"class":3849},[3832,28200,28201],{"class":3834,"line":4091},[3832,28202,3877],{"emptyLinePlaceholder":3876},[3832,28204,28205,28208],{"class":3834,"line":4096},[3832,28206,28207],{"class":3845},"                try",[3832,28209,3897],{"class":3849},[3832,28211,28212],{"class":3834,"line":4102},[3832,28213,28214],{"class":3838},"                    \u002F\u002F 2. Очікуємо на реальну відповідь бекенду\n",[3832,28216,28217,28220],{"class":3834,"line":4123},[3832,28218,28219],{"class":3845},"                    await",[3832,28221,28222],{"class":3853}," queryFulfilled\n",[3832,28224,28225,28227,28229],{"class":3834,"line":4131},[3832,28226,15127],{"class":3849},[3832,28228,20571],{"class":3845},[3832,28230,3897],{"class":3849},[3832,28232,28233],{"class":3834,"line":4145},[3832,28234,28235],{"class":3838},"                    \u002F\u002F 3. ВІДКАТ (ROLLBACK): Якщо сервер повернув 500 або зникла мережа\n",[3832,28237,28238,28241,28243,28246],{"class":3834,"line":4171},[3832,28239,28240],{"class":3853},"                    patchResult",[3832,28242,4183],{"class":3849},[3832,28244,28245],{"class":4117},"undo",[3832,28247,4230],{"class":3849},[3832,28249,28250],{"class":3834,"line":4192},[3832,28251,15165],{"class":3849},[3832,28253,28254],{"class":3834,"line":4211},[3832,28255,13923],{"class":3849},[3832,28257,28258],{"class":3834,"line":4217},[3832,28259,6367],{"class":3849},[3832,28261,28262],{"class":3834,"line":4233},[3832,28263,6475],{"class":3849},[3832,28265,28266],{"class":3834,"line":4239},[3832,28267,4566],{"class":3849},[3832,28269,28270],{"class":3834,"line":4244},[3832,28271,3877],{"emptyLinePlaceholder":3876},[3832,28273,28274,28276,28278,28280,28283,28285],{"class":3834,"line":4249},[3832,28275,4105],{"class":3845},[3832,28277,4108],{"class":3889},[3832,28279,3850],{"class":3849},[3832,28281,28282],{"class":4042},"useToggleTripFavoriteMutation",[3832,28284,4748],{"class":3849},[3832,28286,28287],{"class":3853},"tripsOptimisticApi\n",[3793,28289],{},[3796,28291,28293,28294],{"id":28292},"realtime-оновлення-websockets-через-oncacheentryadded","Realtime-оновлення: WebSockets через ",[3829,28295,28296],{},"onCacheEntryAdded",[3801,28298,28299,28300,4304],{},"Якщо дані на сервері змінюються в реальному часі (наприклад, водій на карті або статус рейсу), RTK Query підтримує підключення WebSockets безпосередньо всередині ендпоінта за допомогою ",[3829,28301,28296],{},[3822,28303,28305],{"className":3824,"code":28304,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fservices\u002FtripsRealtimeApi.ts\nimport { baseApi } from '.\u002FbaseApi'\nimport type { Trip } from '.\u002FtripsApi'\n\nexport const tripsRealtimeApi = baseApi.injectEndpoints({\n    endpoints: (builder) => ({\n        getLiveTripStatus: builder.query\u003CTrip, string>({\n            query: (tripId) => `\u002Ftrips\u002F${tripId}`,\n            async onCacheEntryAdded(tripId, { updateCachedData, cacheDataLoaded, cacheEntryRemoved }) {\n                \u002F\u002F Створюємо WebSocket з'єднання\n                const ws = new WebSocket(`wss:\u002F\u002Fapi.nomad.dev\u002Ftrips\u002F${tripId}\u002Flive`)\n\n                try {\n                    \u002F\u002F Чекаємо поки початковий HTTP-запит успішно виконається\n                    await cacheDataLoaded\n\n                    \u002F\u002F Слухаємо оновлення з сервера\n                    ws.onmessage = (event) => {\n                        const updatedData = JSON.parse(event.data)\n                        \u002F\u002F Прямо оновлюємо поточний запис у кеші\n                        updateCachedData((draft) => {\n                            Object.assign(draft, updatedData)\n                        })\n                    }\n                } catch {\n                    \u002F\u002F Обробка помилки початкового завантаження\n                }\n\n                \u002F\u002F Коли екран закривається і підписка розривається -> закриваємо сокет\n                await cacheEntryRemoved\n                ws.close()\n            },\n        }),\n    }),\n})\n",[3829,28306,28307,28312,28326,28342,28346,28365,28381,28402,28428,28456,28461,28491,28495,28501,28506,28513,28517,28522,28543,28570,28575,28590,28611,28616,28621,28629,28634,28638,28642,28647,28655,28667,28671,28675,28679],{"__ignoreMap":3827},[3832,28308,28309],{"class":3834,"line":3835},[3832,28310,28311],{"class":3838},"\u002F\u002F src\u002Fservices\u002FtripsRealtimeApi.ts\n",[3832,28313,28314,28316,28318,28320,28322,28324],{"class":3834,"line":3842},[3832,28315,3846],{"class":3845},[3832,28317,3850],{"class":3849},[3832,28319,27876],{"class":3853},[3832,28321,3863],{"class":3849},[3832,28323,3866],{"class":3845},[3832,28325,27883],{"class":3869},[3832,28327,28328,28330,28332,28334,28336,28338,28340],{"class":3834,"line":3873},[3832,28329,3846],{"class":3845},[3832,28331,9673],{"class":3845},[3832,28333,3850],{"class":3849},[3832,28335,3977],{"class":3853},[3832,28337,3863],{"class":3849},[3832,28339,3866],{"class":3845},[3832,28341,27900],{"class":3869},[3832,28343,28344],{"class":3834,"line":3880},[3832,28345,3877],{"emptyLinePlaceholder":3876},[3832,28347,28348,28350,28352,28355,28357,28359,28361,28363],{"class":3834,"line":3886},[3832,28349,4105],{"class":3845},[3832,28351,4108],{"class":3889},[3832,28353,28354],{"class":4042}," tripsRealtimeApi",[3832,28356,4114],{"class":3849},[3832,28358,27876],{"class":3853},[3832,28360,4183],{"class":3849},[3832,28362,27922],{"class":4117},[3832,28364,4267],{"class":3849},[3832,28366,28367,28369,28371,28373,28375,28377,28379],{"class":3834,"line":3900},[3832,28368,6288],{"class":4117},[3832,28370,4304],{"class":3853},[3832,28372,4307],{"class":3849},[3832,28374,4310],{"class":3853},[3832,28376,4313],{"class":3849},[3832,28378,4140],{"class":3889},[3832,28380,6301],{"class":3849},[3832,28382,28383,28386,28388,28390,28392,28394,28396,28398,28400],{"class":3834,"line":3912},[3832,28384,28385],{"class":3853},"        getLiveTripStatus:",[3832,28387,6314],{"class":3853},[3832,28389,4183],{"class":3849},[3832,28391,6319],{"class":4117},[3832,28393,5084],{"class":3849},[3832,28395,3977],{"class":3893},[3832,28397,3857],{"class":3849},[3832,28399,4008],{"class":3893},[3832,28401,6332],{"class":3849},[3832,28403,28404,28406,28408,28410,28412,28414,28416,28418,28420,28422,28424,28426],{"class":3834,"line":3922},[3832,28405,6337],{"class":4117},[3832,28407,4304],{"class":3853},[3832,28409,4307],{"class":3849},[3832,28411,8350],{"class":3853},[3832,28413,4313],{"class":3849},[3832,28415,4140],{"class":3889},[3832,28417,21826],{"class":3869},[3832,28419,11249],{"class":3889},[3832,28421,8350],{"class":3853},[3832,28423,4890],{"class":3889},[3832,28425,11514],{"class":3869},[3832,28427,4072],{"class":3849},[3832,28429,28430,28432,28435,28437,28439,28441,28444,28446,28449,28451,28454],{"class":3834,"line":3932},[3832,28431,28038],{"class":3889},[3832,28433,28434],{"class":4117}," onCacheEntryAdded",[3832,28436,4162],{"class":3849},[3832,28438,8350],{"class":3853},[3832,28440,4611],{"class":3849},[3832,28442,28443],{"class":3853},"updateCachedData",[3832,28445,3857],{"class":3849},[3832,28447,28448],{"class":3853},"cacheDataLoaded",[3832,28450,3857],{"class":3849},[3832,28452,28453],{"class":3853},"cacheEntryRemoved",[3832,28455,8353],{"class":3849},[3832,28457,28458],{"class":3834,"line":3942},[3832,28459,28460],{"class":3838},"                \u002F\u002F Створюємо WebSocket з'єднання\n",[3832,28462,28463,28465,28468,28470,28472,28475,28477,28480,28482,28484,28486,28489],{"class":3834,"line":3948},[3832,28464,14926],{"class":3889},[3832,28466,28467],{"class":4042}," ws",[3832,28469,4114],{"class":3849},[3832,28471,7494],{"class":3889},[3832,28473,28474],{"class":4117}," WebSocket",[3832,28476,4162],{"class":3849},[3832,28478,28479],{"class":3869},"`wss:\u002F\u002Fapi.nomad.dev\u002Ftrips\u002F",[3832,28481,11249],{"class":3889},[3832,28483,8350],{"class":3853},[3832,28485,4890],{"class":3889},[3832,28487,28488],{"class":3869},"\u002Flive`",[3832,28490,4168],{"class":3849},[3832,28492,28493],{"class":3834,"line":3953},[3832,28494,3877],{"emptyLinePlaceholder":3876},[3832,28496,28497,28499],{"class":3834,"line":3959},[3832,28498,28207],{"class":3845},[3832,28500,3897],{"class":3849},[3832,28502,28503],{"class":3834,"line":3969},[3832,28504,28505],{"class":3838},"                    \u002F\u002F Чекаємо поки початковий HTTP-запит успішно виконається\n",[3832,28507,28508,28510],{"class":3834,"line":3986},[3832,28509,28219],{"class":3845},[3832,28511,28512],{"class":3853}," cacheDataLoaded\n",[3832,28514,28515],{"class":3834,"line":4000},[3832,28516,3877],{"emptyLinePlaceholder":3876},[3832,28518,28519],{"class":3834,"line":4020},[3832,28520,28521],{"class":3838},"                    \u002F\u002F Слухаємо оновлення з сервера\n",[3832,28523,28524,28527,28529,28532,28534,28537,28539,28541],{"class":3834,"line":4025},[3832,28525,28526],{"class":3853},"                    ws",[3832,28528,4183],{"class":3849},[3832,28530,28531],{"class":4117},"onmessage",[3832,28533,11450],{"class":3849},[3832,28535,28536],{"class":3853},"event",[3832,28538,4313],{"class":3849},[3832,28540,4140],{"class":3889},[3832,28542,3897],{"class":3849},[3832,28544,28545,28547,28550,28552,28555,28557,28560,28562,28564,28566,28568],{"class":3834,"line":4030},[3832,28546,28120],{"class":3889},[3832,28548,28549],{"class":4042}," updatedData",[3832,28551,4114],{"class":3849},[3832,28553,28554],{"class":4042},"JSON",[3832,28556,4183],{"class":3849},[3832,28558,28559],{"class":4117},"parse",[3832,28561,4162],{"class":3849},[3832,28563,28536],{"class":3853},[3832,28565,4183],{"class":3849},[3832,28567,6565],{"class":3853},[3832,28569,4168],{"class":3849},[3832,28571,28572],{"class":3834,"line":4036},[3832,28573,28574],{"class":3838},"                        \u002F\u002F Прямо оновлюємо поточний запис у кеші\n",[3832,28576,28577,28580,28582,28584,28586,28588],{"class":3834,"line":4054},[3832,28578,28579],{"class":4117},"                        updateCachedData",[3832,28581,4753],{"class":3849},[3832,28583,28105],{"class":3853},[3832,28585,4313],{"class":3849},[3832,28587,4140],{"class":3889},[3832,28589,3897],{"class":3849},[3832,28591,28592,28595,28597,28600,28602,28604,28606,28609],{"class":3834,"line":4063},[3832,28593,28594],{"class":3853},"                            Object",[3832,28596,4183],{"class":3849},[3832,28598,28599],{"class":4117},"assign",[3832,28601,4162],{"class":3849},[3832,28603,28105],{"class":3853},[3832,28605,3857],{"class":3849},[3832,28607,28608],{"class":3853},"updatedData",[3832,28610,4168],{"class":3849},[3832,28612,28613],{"class":3834,"line":4075},[3832,28614,28615],{"class":3849},"                        })\n",[3832,28617,28618],{"class":3834,"line":4086},[3832,28619,28620],{"class":3849},"                    }\n",[3832,28622,28623,28625,28627],{"class":3834,"line":4091},[3832,28624,15127],{"class":3849},[3832,28626,20571],{"class":3845},[3832,28628,3897],{"class":3849},[3832,28630,28631],{"class":3834,"line":4096},[3832,28632,28633],{"class":3838},"                    \u002F\u002F Обробка помилки початкового завантаження\n",[3832,28635,28636],{"class":3834,"line":4102},[3832,28637,15165],{"class":3849},[3832,28639,28640],{"class":3834,"line":4123},[3832,28641,3877],{"emptyLinePlaceholder":3876},[3832,28643,28644],{"class":3834,"line":4131},[3832,28645,28646],{"class":3838},"                \u002F\u002F Коли екран закривається і підписка розривається -> закриваємо сокет\n",[3832,28648,28649,28652],{"class":3834,"line":4145},[3832,28650,28651],{"class":3845},"                await",[3832,28653,28654],{"class":3853}," cacheEntryRemoved\n",[3832,28656,28657,28660,28662,28665],{"class":3834,"line":4171},[3832,28658,28659],{"class":3853},"                ws",[3832,28661,4183],{"class":3849},[3832,28663,28664],{"class":4117},"close",[3832,28666,4230],{"class":3849},[3832,28668,28669],{"class":3834,"line":4192},[3832,28670,13923],{"class":3849},[3832,28672,28673],{"class":3834,"line":4211},[3832,28674,6367],{"class":3849},[3832,28676,28677],{"class":3834,"line":4217},[3832,28678,6475],{"class":3849},[3832,28680,28681],{"class":3834,"line":4233},[3832,28682,4566],{"class":3849},[3793,28684],{},[3796,28686,28688],{"id":28687},"пагінація-та-infinite-scroll-у-списках","Пагінація та Infinite Scroll у списках",[3801,28690,28691,28692,28695,28696,18007,28699,4304],{},"Для великих мобільних стрічок завантаження всіх даних одразу призведе до вичерпання оперативної пам'яті. RTK Query дозволяє легко реалізувати нескінченний скрол (",[3817,28693,28694],{},"Infinite Scroll",") шляхом об'єднання сторінок за допомогою функцій ",[3829,28697,28698],{},"serializeQueryArgs",[3829,28700,28701],{},"merge",[3822,28703,28705],{"className":3824,"code":28704,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fservices\u002FtripsPaginationApi.ts\nimport { baseApi } from '.\u002FbaseApi'\nimport type { Trip } from '.\u002FtripsApi'\n\nexport interface PaginatedResponse {\n    items: Trip[]\n    nextPage: number | null\n    total: number\n}\n\nexport const tripsPaginationApi = baseApi.injectEndpoints({\n    endpoints: (builder) => ({\n        getInfiniteTrips: builder.query\u003CPaginatedResponse, number>({\n            query: (page = 1) => `\u002Ftrips?_page=${page}&_limit=10`,\n\n            \u002F\u002F 1. Один спільний ключ кешу для всіх сторінок цього ендпоінта\n            serializeQueryArgs: ({ endpointName }) => {\n                return endpointName\n            },\n\n            \u002F\u002F 2. Злиття нових сторінок з існуючим кешем списку\n            merge: (currentCache, newItems) => {\n                if (newItems.nextPage === 2) {\n                    currentCache.items = newItems.items\n                } else {\n                    currentCache.items.push(...newItems.items)\n                }\n                currentCache.nextPage = newItems.nextPage\n                currentCache.total = newItems.total\n            },\n\n            \u002F\u002F 3. Примусовий перезапит при зміні номера сторінки\n            forceRefetch({ currentArg, previousArg }) {\n                return currentArg !== previousArg\n            },\n        }),\n    }),\n})\n\nexport const { useGetInfiniteTripsQuery } = tripsPaginationApi\n",[3829,28706,28707,28712,28726,28742,28746,28758,28769,28782,28791,28795,28799,28818,28834,28856,28890,28894,28899,28917,28924,28928,28932,28937,28960,28979,28996,29004,29027,29031,29049,29067,29071,29075,29080,29097,29109,29113,29117,29121,29125,29129],{"__ignoreMap":3827},[3832,28708,28709],{"class":3834,"line":3835},[3832,28710,28711],{"class":3838},"\u002F\u002F src\u002Fservices\u002FtripsPaginationApi.ts\n",[3832,28713,28714,28716,28718,28720,28722,28724],{"class":3834,"line":3842},[3832,28715,3846],{"class":3845},[3832,28717,3850],{"class":3849},[3832,28719,27876],{"class":3853},[3832,28721,3863],{"class":3849},[3832,28723,3866],{"class":3845},[3832,28725,27883],{"class":3869},[3832,28727,28728,28730,28732,28734,28736,28738,28740],{"class":3834,"line":3873},[3832,28729,3846],{"class":3845},[3832,28731,9673],{"class":3845},[3832,28733,3850],{"class":3849},[3832,28735,3977],{"class":3853},[3832,28737,3863],{"class":3849},[3832,28739,3866],{"class":3845},[3832,28741,27900],{"class":3869},[3832,28743,28744],{"class":3834,"line":3880},[3832,28745,3877],{"emptyLinePlaceholder":3876},[3832,28747,28748,28750,28753,28756],{"class":3834,"line":3886},[3832,28749,4105],{"class":3845},[3832,28751,28752],{"class":3889}," interface",[3832,28754,28755],{"class":3893}," PaginatedResponse",[3832,28757,3897],{"class":3849},[3832,28759,28760,28763,28765,28767],{"class":3834,"line":3900},[3832,28761,28762],{"class":3853},"    items",[3832,28764,3906],{"class":3849},[3832,28766,3977],{"class":3893},[3832,28768,5653],{"class":3849},[3832,28770,28771,28774,28776,28778,28780],{"class":3834,"line":3912},[3832,28772,28773],{"class":3853},"    nextPage",[3832,28775,3906],{"class":3849},[3832,28777,5663],{"class":3893},[3832,28779,4011],{"class":3849},[3832,28781,4391],{"class":3893},[3832,28783,28784,28787,28789],{"class":3834,"line":3922},[3832,28785,28786],{"class":3853},"    total",[3832,28788,3906],{"class":3849},[3832,28790,9238],{"class":3893},[3832,28792,28793],{"class":3834,"line":3932},[3832,28794,3945],{"class":3849},[3832,28796,28797],{"class":3834,"line":3942},[3832,28798,3877],{"emptyLinePlaceholder":3876},[3832,28800,28801,28803,28805,28808,28810,28812,28814,28816],{"class":3834,"line":3948},[3832,28802,4105],{"class":3845},[3832,28804,4108],{"class":3889},[3832,28806,28807],{"class":4042}," tripsPaginationApi",[3832,28809,4114],{"class":3849},[3832,28811,27876],{"class":3853},[3832,28813,4183],{"class":3849},[3832,28815,27922],{"class":4117},[3832,28817,4267],{"class":3849},[3832,28819,28820,28822,28824,28826,28828,28830,28832],{"class":3834,"line":3953},[3832,28821,6288],{"class":4117},[3832,28823,4304],{"class":3853},[3832,28825,4307],{"class":3849},[3832,28827,4310],{"class":3853},[3832,28829,4313],{"class":3849},[3832,28831,4140],{"class":3889},[3832,28833,6301],{"class":3849},[3832,28835,28836,28839,28841,28843,28845,28847,28850,28852,28854],{"class":3834,"line":3959},[3832,28837,28838],{"class":3853},"        getInfiniteTrips:",[3832,28840,6314],{"class":3853},[3832,28842,4183],{"class":3849},[3832,28844,6319],{"class":4117},[3832,28846,5084],{"class":3849},[3832,28848,28849],{"class":3893},"PaginatedResponse",[3832,28851,3857],{"class":3849},[3832,28853,5663],{"class":3893},[3832,28855,6332],{"class":3849},[3832,28857,28858,28860,28862,28864,28867,28869,28872,28874,28876,28879,28881,28883,28885,28888],{"class":3834,"line":3969},[3832,28859,6337],{"class":4117},[3832,28861,4304],{"class":3853},[3832,28863,4307],{"class":3849},[3832,28865,28866],{"class":3853},"page",[3832,28868,4114],{"class":3849},[3832,28870,28871],{"class":5726},"1",[3832,28873,4313],{"class":3849},[3832,28875,4140],{"class":3889},[3832,28877,28878],{"class":3869}," `\u002Ftrips?_page=",[3832,28880,11249],{"class":3889},[3832,28882,28866],{"class":3853},[3832,28884,4890],{"class":3889},[3832,28886,28887],{"class":3869},"&_limit=10`",[3832,28889,4072],{"class":3849},[3832,28891,28892],{"class":3834,"line":3986},[3832,28893,3877],{"emptyLinePlaceholder":3876},[3832,28895,28896],{"class":3834,"line":4000},[3832,28897,28898],{"class":3838},"            \u002F\u002F 1. Один спільний ключ кешу для всіх сторінок цього ендпоінта\n",[3832,28900,28901,28904,28906,28908,28911,28913,28915],{"class":3834,"line":4020},[3832,28902,28903],{"class":4117},"            serializeQueryArgs",[3832,28905,4304],{"class":3853},[3832,28907,19679],{"class":3849},[3832,28909,28910],{"class":3853},"endpointName",[3832,28912,4981],{"class":3849},[3832,28914,4140],{"class":3889},[3832,28916,3897],{"class":3849},[3832,28918,28919,28921],{"class":3834,"line":4025},[3832,28920,16712],{"class":3845},[3832,28922,28923],{"class":3853}," endpointName\n",[3832,28925,28926],{"class":3834,"line":4030},[3832,28927,13923],{"class":3849},[3832,28929,28930],{"class":3834,"line":4036},[3832,28931,3877],{"emptyLinePlaceholder":3876},[3832,28933,28934],{"class":3834,"line":4054},[3832,28935,28936],{"class":3838},"            \u002F\u002F 2. Злиття нових сторінок з існуючим кешем списку\n",[3832,28938,28939,28942,28944,28946,28949,28951,28954,28956,28958],{"class":3834,"line":4063},[3832,28940,28941],{"class":4117},"            merge",[3832,28943,4304],{"class":3853},[3832,28945,4307],{"class":3849},[3832,28947,28948],{"class":3853},"currentCache",[3832,28950,3857],{"class":3849},[3832,28952,28953],{"class":3853},"newItems",[3832,28955,4313],{"class":3849},[3832,28957,4140],{"class":3889},[3832,28959,3897],{"class":3849},[3832,28961,28962,28964,28966,28968,28970,28973,28975,28977],{"class":3834,"line":4075},[3832,28963,15035],{"class":3845},[3832,28965,4307],{"class":3849},[3832,28967,28953],{"class":3853},[3832,28969,4183],{"class":3849},[3832,28971,28972],{"class":3853},"nextPage",[3832,28974,5921],{"class":3849},[3832,28976,27721],{"class":5726},[3832,28978,4189],{"class":3849},[3832,28980,28981,28984,28986,28988,28990,28992,28994],{"class":3834,"line":4086},[3832,28982,28983],{"class":3853},"                    currentCache",[3832,28985,4183],{"class":3849},[3832,28987,17471],{"class":3853},[3832,28989,4114],{"class":3849},[3832,28991,28953],{"class":3853},[3832,28993,4183],{"class":3849},[3832,28995,17525],{"class":3853},[3832,28997,28998,29000,29002],{"class":3834,"line":4091},[3832,28999,15127],{"class":3849},[3832,29001,14059],{"class":3845},[3832,29003,3897],{"class":3849},[3832,29005,29006,29008,29010,29012,29014,29016,29019,29021,29023,29025],{"class":3834,"line":4096},[3832,29007,28983],{"class":3853},[3832,29009,4183],{"class":3849},[3832,29011,17471],{"class":3853},[3832,29013,4183],{"class":3849},[3832,29015,5327],{"class":4117},[3832,29017,29018],{"class":3849},"(...",[3832,29020,28953],{"class":3853},[3832,29022,4183],{"class":3849},[3832,29024,17471],{"class":3853},[3832,29026,4168],{"class":3849},[3832,29028,29029],{"class":3834,"line":4102},[3832,29030,15165],{"class":3849},[3832,29032,29033,29036,29038,29040,29042,29044,29046],{"class":3834,"line":4123},[3832,29034,29035],{"class":3853},"                currentCache",[3832,29037,4183],{"class":3849},[3832,29039,28972],{"class":3853},[3832,29041,4114],{"class":3849},[3832,29043,28953],{"class":3853},[3832,29045,4183],{"class":3849},[3832,29047,29048],{"class":3853},"nextPage\n",[3832,29050,29051,29053,29055,29058,29060,29062,29064],{"class":3834,"line":4131},[3832,29052,29035],{"class":3853},[3832,29054,4183],{"class":3849},[3832,29056,29057],{"class":3853},"total",[3832,29059,4114],{"class":3849},[3832,29061,28953],{"class":3853},[3832,29063,4183],{"class":3849},[3832,29065,29066],{"class":3853},"total\n",[3832,29068,29069],{"class":3834,"line":4145},[3832,29070,13923],{"class":3849},[3832,29072,29073],{"class":3834,"line":4171},[3832,29074,3877],{"emptyLinePlaceholder":3876},[3832,29076,29077],{"class":3834,"line":4192},[3832,29078,29079],{"class":3838},"            \u002F\u002F 3. Примусовий перезапит при зміні номера сторінки\n",[3832,29081,29082,29085,29087,29090,29092,29095],{"class":3834,"line":4211},[3832,29083,29084],{"class":4117},"            forceRefetch",[3832,29086,4976],{"class":3849},[3832,29088,29089],{"class":3853},"currentArg",[3832,29091,3857],{"class":3849},[3832,29093,29094],{"class":3853},"previousArg",[3832,29096,8353],{"class":3849},[3832,29098,29099,29101,29104,29106],{"class":3834,"line":4217},[3832,29100,16712],{"class":3845},[3832,29102,29103],{"class":3853}," currentArg",[3832,29105,16875],{"class":3849},[3832,29107,29108],{"class":3853},"previousArg\n",[3832,29110,29111],{"class":3834,"line":4233},[3832,29112,13923],{"class":3849},[3832,29114,29115],{"class":3834,"line":4239},[3832,29116,6367],{"class":3849},[3832,29118,29119],{"class":3834,"line":4244},[3832,29120,6475],{"class":3849},[3832,29122,29123],{"class":3834,"line":4249},[3832,29124,4566],{"class":3849},[3832,29126,29127],{"class":3834,"line":4255},[3832,29128,3877],{"emptyLinePlaceholder":3876},[3832,29130,29131,29133,29135,29137,29140,29142],{"class":3834,"line":4270},[3832,29132,4105],{"class":3845},[3832,29134,4108],{"class":3889},[3832,29136,3850],{"class":3849},[3832,29138,29139],{"class":4042},"useGetInfiniteTripsQuery",[3832,29141,4748],{"class":3849},[3832,29143,29144],{"class":3853},"tripsPaginationApi\n",[3793,29146],{},[3796,29148,29150],{"id":29149},"міні-проєкт-нотатки-мандрівника-з-rtk-query","Міні-проєкт: «Нотатки мандрівника» з RTK Query",[3801,29152,29153],{},"Побудуємо повнофункціональний міні-застосунок для керування нотатками з використанням віддаленого REST API.",[3809,29155,29157],{"id":29156},"структура-файлової-системи-міні-проєкту","Структура файлової системи міні-проєкту",[29159,29160,29161,29168,29175,29182],"code-tree",{},[3822,29162,29166],{"className":29163,"code":29164,"filename":29165,"language":13010,"meta":3827},[13008],"Опис ендпоінтів для читання, додавання та видалення нотаток\n","src\u002Fservices\u002FnotesApi.ts",[3829,29167,29164],{"__ignoreMap":3827},[3822,29169,29173],{"className":29170,"code":29171,"filename":29172,"language":13010,"meta":3827},[13008],"Конфігурація Store з підключенням notesApi\n","src\u002Fstore\u002Findex.ts",[3829,29174,29171],{"__ignoreMap":3827},[3822,29176,29180],{"className":29177,"code":29178,"filename":29179,"language":13010,"meta":3827},[13008],"Головний екран зі списком, Pull-to-Refresh та обробкою помилок\n","src\u002Fscreens\u002FNotesScreen.tsx",[3829,29181,29178],{"__ignoreMap":3827},[3822,29183,29187],{"className":29184,"code":29185,"filename":29186,"language":13010,"meta":3827},[13008],"Точка входу з Redux Provider\n","App.tsx",[3829,29188,29185],{"__ignoreMap":3827},[3809,29190,29192],{"id":29191},"кроки-реалізації","Кроки реалізації",[5430,29194,29195,29202,29762,29766,29913,29920],{},[3809,29196,29198,29199],{"id":29197},"крок-1-створення-сервісу-notesapits","Крок 1. Створення сервісу ",[3829,29200,29201],{},"notesApi.ts",[3822,29203,29205],{"className":3824,"code":29204,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fservices\u002FnotesApi.ts\nimport { createApi, fetchBaseQuery } from '@reduxjs\u002Ftoolkit\u002Fquery\u002Freact'\n\nexport interface Note {\n    id: number\n    title: string\n    body: string\n    userId: number\n}\n\nexport const notesApi = createApi({\n    reducerPath: 'notesApi',\n    baseQuery: fetchBaseQuery({ baseUrl: 'https:\u002F\u002Fjsonplaceholder.typicode.com' }),\n    tagTypes: ['Note'],\n    endpoints: (builder) => ({\n        getNotes: builder.query\u003CNote[], void>({\n            query: () => '\u002Fposts?_limit=15',\n            providesTags: (result) =>\n                result\n                    ? [...result.map(({ id }) => ({ type: 'Note' as const, id })), { type: 'Note', id: 'LIST' }]\n                    : [{ type: 'Note', id: 'LIST' }],\n        }),\n\n        createNote: builder.mutation\u003CNote, { title: string; body: string }>({\n            query: (payload) => ({\n                url: '\u002Fposts',\n                method: 'POST',\n                body: { ...payload, userId: 1 },\n            }),\n            invalidatesTags: [{ type: 'Note', id: 'LIST' }],\n        }),\n\n        deleteNote: builder.mutation\u003C{ success: boolean }, number>({\n            query: (noteId) => ({\n                url: `\u002Fposts\u002F${noteId}`,\n                method: 'DELETE',\n            }),\n            invalidatesTags: (_result, _error, id) => [\n                { type: 'Note', id },\n                { type: 'Note', id: 'LIST' },\n            ],\n        }),\n    }),\n})\n\nexport const { useGetNotesQuery, useCreateNoteMutation, useDeleteNoteMutation } = notesApi\n",[3829,29206,29207,29212,29230,29234,29245,29253,29261,29269,29278,29282,29286,29301,29310,29324,29335,29351,29373,29388,29402,29406,29455,29471,29475,29479,29512,29528,29536,29544,29562,29566,29584,29588,29592,29617,29634,29650,29658,29662,29686,29700,29716,29720,29724,29728,29732,29736],{"__ignoreMap":3827},[3832,29208,29209],{"class":3834,"line":3835},[3832,29210,29211],{"class":3838},"\u002F\u002F src\u002Fservices\u002FnotesApi.ts\n",[3832,29213,29214,29216,29218,29220,29222,29224,29226,29228],{"class":3834,"line":3842},[3832,29215,3846],{"class":3845},[3832,29217,3850],{"class":3849},[3832,29219,6153],{"class":3853},[3832,29221,3857],{"class":3849},[3832,29223,6158],{"class":3853},[3832,29225,3863],{"class":3849},[3832,29227,3866],{"class":3845},[3832,29229,6165],{"class":3869},[3832,29231,29232],{"class":3834,"line":3873},[3832,29233,3877],{"emptyLinePlaceholder":3876},[3832,29235,29236,29238,29240,29243],{"class":3834,"line":3880},[3832,29237,4105],{"class":3845},[3832,29239,28752],{"class":3889},[3832,29241,29242],{"class":3893}," Note",[3832,29244,3897],{"class":3849},[3832,29246,29247,29249,29251],{"class":3834,"line":3886},[3832,29248,3903],{"class":3853},[3832,29250,3906],{"class":3849},[3832,29252,9238],{"class":3893},[3832,29254,29255,29257,29259],{"class":3834,"line":3900},[3832,29256,3915],{"class":3853},[3832,29258,3906],{"class":3849},[3832,29260,3909],{"class":3893},[3832,29262,29263,29265,29267],{"class":3834,"line":3912},[3832,29264,9251],{"class":3853},[3832,29266,3906],{"class":3849},[3832,29268,3909],{"class":3893},[3832,29270,29271,29274,29276],{"class":3834,"line":3922},[3832,29272,29273],{"class":3853},"    userId",[3832,29275,3906],{"class":3849},[3832,29277,9238],{"class":3893},[3832,29279,29280],{"class":3834,"line":3932},[3832,29281,3945],{"class":3849},[3832,29283,29284],{"class":3834,"line":3942},[3832,29285,3877],{"emptyLinePlaceholder":3876},[3832,29287,29288,29290,29292,29295,29297,29299],{"class":3834,"line":3948},[3832,29289,4105],{"class":3845},[3832,29291,4108],{"class":3889},[3832,29293,29294],{"class":4042}," notesApi",[3832,29296,4114],{"class":3849},[3832,29298,6153],{"class":4117},[3832,29300,4267],{"class":3849},[3832,29302,29303,29305,29308],{"class":3834,"line":3953},[3832,29304,6242],{"class":3853},[3832,29306,29307],{"class":3869}," 'notesApi'",[3832,29309,4072],{"class":3849},[3832,29311,29312,29314,29316,29318,29320,29322],{"class":3834,"line":3959},[3832,29313,6252],{"class":3853},[3832,29315,6255],{"class":4117},[3832,29317,4976],{"class":3849},[3832,29319,6260],{"class":3853},[3832,29321,9322],{"class":3869},[3832,29323,6266],{"class":3849},[3832,29325,29326,29328,29330,29333],{"class":3834,"line":3969},[3832,29327,6271],{"class":3853},[3832,29329,6274],{"class":3849},[3832,29331,29332],{"class":3869},"'Note'",[3832,29334,11605],{"class":3849},[3832,29336,29337,29339,29341,29343,29345,29347,29349],{"class":3834,"line":3986},[3832,29338,6288],{"class":4117},[3832,29340,4304],{"class":3853},[3832,29342,4307],{"class":3849},[3832,29344,4310],{"class":3853},[3832,29346,4313],{"class":3849},[3832,29348,4140],{"class":3889},[3832,29350,6301],{"class":3849},[3832,29352,29353,29356,29358,29360,29362,29364,29367,29369,29371],{"class":3834,"line":4000},[3832,29354,29355],{"class":3853},"        getNotes:",[3832,29357,6314],{"class":3853},[3832,29359,4183],{"class":3849},[3832,29361,6319],{"class":4117},[3832,29363,5084],{"class":3849},[3832,29365,29366],{"class":3893},"Note",[3832,29368,6326],{"class":3849},[3832,29370,6329],{"class":3893},[3832,29372,6332],{"class":3849},[3832,29374,29375,29377,29379,29381,29383,29386],{"class":3834,"line":4020},[3832,29376,6337],{"class":4117},[3832,29378,4304],{"class":3853},[3832,29380,4137],{"class":3849},[3832,29382,4140],{"class":3889},[3832,29384,29385],{"class":3869}," '\u002Fposts?_limit=15'",[3832,29387,4072],{"class":3849},[3832,29389,29390,29392,29394,29396,29398,29400],{"class":3834,"line":4025},[3832,29391,25270],{"class":4117},[3832,29393,4304],{"class":3853},[3832,29395,4307],{"class":3849},[3832,29397,13782],{"class":3853},[3832,29399,4313],{"class":3849},[3832,29401,9607],{"class":3889},[3832,29403,29404],{"class":3834,"line":4030},[3832,29405,25285],{"class":3853},[3832,29407,29408,29410,29412,29414,29416,29419,29421,29423,29425,29427,29429,29432,29434,29436,29438,29440,29443,29445,29447,29449,29451,29453],{"class":3834,"line":4036},[3832,29409,26641],{"class":3849},[3832,29411,13782],{"class":3853},[3832,29413,4183],{"class":3849},[3832,29415,17783],{"class":4117},[3832,29417,29418],{"class":3849},"(({ ",[3832,29420,4962],{"class":3853},[3832,29422,4981],{"class":3849},[3832,29424,4140],{"class":3889},[3832,29426,19679],{"class":3849},[3832,29428,21896],{"class":3853},[3832,29430,29431],{"class":3869}," 'Note'",[3832,29433,14013],{"class":3845},[3832,29435,4108],{"class":3889},[3832,29437,3857],{"class":3849},[3832,29439,4962],{"class":3853},[3832,29441,29442],{"class":3849}," })), { ",[3832,29444,21896],{"class":3853},[3832,29446,29431],{"class":3869},[3832,29448,3857],{"class":3849},[3832,29450,22383],{"class":3853},[3832,29452,22402],{"class":3869},[3832,29454,25931],{"class":3849},[3832,29456,29457,29459,29461,29463,29465,29467,29469],{"class":3834,"line":4054},[3832,29458,25359],{"class":3849},[3832,29460,21896],{"class":3853},[3832,29462,29431],{"class":3869},[3832,29464,3857],{"class":3849},[3832,29466,22383],{"class":3853},[3832,29468,22402],{"class":3869},[3832,29470,25372],{"class":3849},[3832,29472,29473],{"class":3834,"line":4063},[3832,29474,6367],{"class":3849},[3832,29476,29477],{"class":3834,"line":4075},[3832,29478,3877],{"emptyLinePlaceholder":3876},[3832,29480,29481,29484,29486,29488,29490,29492,29494,29496,29498,29500,29502,29504,29506,29508,29510],{"class":3834,"line":4086},[3832,29482,29483],{"class":3853},"        createNote:",[3832,29485,6314],{"class":3853},[3832,29487,4183],{"class":3849},[3832,29489,6384],{"class":4117},[3832,29491,5084],{"class":3849},[3832,29493,29366],{"class":3893},[3832,29495,4611],{"class":3849},[3832,29497,4998],{"class":3853},[3832,29499,3906],{"class":3849},[3832,29501,4008],{"class":3893},[3832,29503,12378],{"class":3849},[3832,29505,10327],{"class":3853},[3832,29507,3906],{"class":3849},[3832,29509,4008],{"class":3893},[3832,29511,24993],{"class":3849},[3832,29513,29514,29516,29518,29520,29522,29524,29526],{"class":3834,"line":4091},[3832,29515,6337],{"class":4117},[3832,29517,4304],{"class":3853},[3832,29519,4307],{"class":3849},[3832,29521,5336],{"class":3853},[3832,29523,4313],{"class":3849},[3832,29525,4140],{"class":3889},[3832,29527,6301],{"class":3849},[3832,29529,29530,29532,29534],{"class":3834,"line":4096},[3832,29531,6424],{"class":3853},[3832,29533,9393],{"class":3869},[3832,29535,4072],{"class":3849},[3832,29537,29538,29540,29542],{"class":3834,"line":4102},[3832,29539,6433],{"class":3853},[3832,29541,5125],{"class":3869},[3832,29543,4072],{"class":3849},[3832,29545,29546,29548,29551,29553,29555,29558,29560],{"class":3834,"line":4123},[3832,29547,6442],{"class":3853},[3832,29549,29550],{"class":3849}," { ...",[3832,29552,5336],{"class":3853},[3832,29554,3857],{"class":3849},[3832,29556,29557],{"class":3853},"userId:",[3832,29559,10411],{"class":5726},[3832,29561,5145],{"class":3849},[3832,29563,29564],{"class":3834,"line":4131},[3832,29565,6452],{"class":3849},[3832,29567,29568,29570,29572,29574,29576,29578,29580,29582],{"class":3834,"line":4145},[3832,29569,6457],{"class":3853},[3832,29571,25457],{"class":3849},[3832,29573,21896],{"class":3853},[3832,29575,29431],{"class":3869},[3832,29577,3857],{"class":3849},[3832,29579,22383],{"class":3853},[3832,29581,22402],{"class":3869},[3832,29583,25372],{"class":3849},[3832,29585,29586],{"class":3834,"line":4171},[3832,29587,6367],{"class":3849},[3832,29589,29590],{"class":3834,"line":4192},[3832,29591,3877],{"emptyLinePlaceholder":3876},[3832,29593,29594,29597,29599,29601,29603,29605,29607,29609,29611,29613,29615],{"class":3834,"line":4211},[3832,29595,29596],{"class":3853},"        deleteNote:",[3832,29598,6314],{"class":3853},[3832,29600,4183],{"class":3849},[3832,29602,6384],{"class":4117},[3832,29604,12498],{"class":3849},[3832,29606,21601],{"class":3853},[3832,29608,3906],{"class":3849},[3832,29610,3994],{"class":3893},[3832,29612,22297],{"class":3849},[3832,29614,5663],{"class":3893},[3832,29616,6332],{"class":3849},[3832,29618,29619,29621,29623,29625,29628,29630,29632],{"class":3834,"line":4217},[3832,29620,6337],{"class":4117},[3832,29622,4304],{"class":3853},[3832,29624,4307],{"class":3849},[3832,29626,29627],{"class":3853},"noteId",[3832,29629,4313],{"class":3849},[3832,29631,4140],{"class":3889},[3832,29633,6301],{"class":3849},[3832,29635,29636,29638,29640,29642,29644,29646,29648],{"class":3834,"line":4233},[3832,29637,6424],{"class":3853},[3832,29639,15993],{"class":3869},[3832,29641,11249],{"class":3889},[3832,29643,29627],{"class":3853},[3832,29645,4890],{"class":3889},[3832,29647,11514],{"class":3869},[3832,29649,4072],{"class":3849},[3832,29651,29652,29654,29656],{"class":3834,"line":4239},[3832,29653,6433],{"class":3853},[3832,29655,22340],{"class":3869},[3832,29657,4072],{"class":3849},[3832,29659,29660],{"class":3834,"line":4244},[3832,29661,6452],{"class":3849},[3832,29663,29664,29666,29668,29670,29672,29674,29676,29678,29680,29682,29684],{"class":3834,"line":4249},[3832,29665,21866],{"class":4117},[3832,29667,4304],{"class":3853},[3832,29669,4307],{"class":3849},[3832,29671,21873],{"class":3853},[3832,29673,3857],{"class":3849},[3832,29675,21878],{"class":3853},[3832,29677,3857],{"class":3849},[3832,29679,4962],{"class":3853},[3832,29681,4313],{"class":3849},[3832,29683,4140],{"class":3889},[3832,29685,21134],{"class":3849},[3832,29687,29688,29690,29692,29694,29696,29698],{"class":3834,"line":4255},[3832,29689,21893],{"class":3849},[3832,29691,21896],{"class":3853},[3832,29693,29431],{"class":3869},[3832,29695,3857],{"class":3849},[3832,29697,4962],{"class":3853},[3832,29699,5145],{"class":3849},[3832,29701,29702,29704,29706,29708,29710,29712,29714],{"class":3834,"line":4270},[3832,29703,21893],{"class":3849},[3832,29705,21896],{"class":3853},[3832,29707,29431],{"class":3869},[3832,29709,3857],{"class":3849},[3832,29711,22383],{"class":3853},[3832,29713,22402],{"class":3869},[3832,29715,5145],{"class":3849},[3832,29717,29718],{"class":3834,"line":4281},[3832,29719,21914],{"class":3849},[3832,29721,29722],{"class":3834,"line":4289},[3832,29723,6367],{"class":3849},[3832,29725,29726],{"class":3834,"line":4298},[3832,29727,6475],{"class":3849},[3832,29729,29730],{"class":3834,"line":4320},[3832,29731,4566],{"class":3849},[3832,29733,29734],{"class":3834,"line":4326},[3832,29735,3877],{"emptyLinePlaceholder":3876},[3832,29737,29738,29740,29742,29744,29747,29749,29752,29754,29757,29759],{"class":3834,"line":4332},[3832,29739,4105],{"class":3845},[3832,29741,4108],{"class":3889},[3832,29743,3850],{"class":3849},[3832,29745,29746],{"class":4042},"useGetNotesQuery",[3832,29748,3857],{"class":3849},[3832,29750,29751],{"class":4042},"useCreateNoteMutation",[3832,29753,3857],{"class":3849},[3832,29755,29756],{"class":4042},"useDeleteNoteMutation",[3832,29758,4748],{"class":3849},[3832,29760,29761],{"class":3853},"notesApi\n",[3809,29763,29765],{"id":29764},"крок-2-налаштування-store","Крок 2. Налаштування Store",[3822,29767,29769],{"className":3824,"code":29768,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fstore\u002Findex.ts\nimport { configureStore } from '@reduxjs\u002Ftoolkit'\nimport { setupListeners } from '@reduxjs\u002Ftoolkit\u002Fquery'\nimport { notesApi } from '@\u002Fservices\u002FnotesApi'\n\nexport const store = configureStore({\n    reducer: {\n        [notesApi.reducerPath]: notesApi.reducer,\n    },\n    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(notesApi.middleware),\n})\n\nsetupListeners(store.dispatch)\n",[3829,29770,29771,29775,29789,29803,29819,29823,29837,29843,29856,29860,29891,29895,29899],{"__ignoreMap":3827},[3832,29772,29773],{"class":3834,"line":3835},[3832,29774,9494],{"class":3838},[3832,29776,29777,29779,29781,29783,29785,29787],{"class":3834,"line":3842},[3832,29778,3846],{"class":3845},[3832,29780,3850],{"class":3849},[3832,29782,9503],{"class":3853},[3832,29784,3863],{"class":3849},[3832,29786,3866],{"class":3845},[3832,29788,3870],{"class":3869},[3832,29790,29791,29793,29795,29797,29799,29801],{"class":3834,"line":3873},[3832,29792,3846],{"class":3845},[3832,29794,3850],{"class":3849},[3832,29796,9518],{"class":3853},[3832,29798,3863],{"class":3849},[3832,29800,3866],{"class":3845},[3832,29802,9525],{"class":3869},[3832,29804,29805,29807,29809,29812,29814,29816],{"class":3834,"line":3880},[3832,29806,3846],{"class":3845},[3832,29808,3850],{"class":3849},[3832,29810,29811],{"class":3853},"notesApi",[3832,29813,3863],{"class":3849},[3832,29815,3866],{"class":3845},[3832,29817,29818],{"class":3869}," '@\u002Fservices\u002FnotesApi'\n",[3832,29820,29821],{"class":3834,"line":3886},[3832,29822,3877],{"emptyLinePlaceholder":3876},[3832,29824,29825,29827,29829,29831,29833,29835],{"class":3834,"line":3900},[3832,29826,4105],{"class":3845},[3832,29828,4108],{"class":3889},[3832,29830,9554],{"class":4042},[3832,29832,4114],{"class":3849},[3832,29834,9503],{"class":4117},[3832,29836,4267],{"class":3849},[3832,29838,29839,29841],{"class":3834,"line":3912},[3832,29840,9565],{"class":3853},[3832,29842,3897],{"class":3849},[3832,29844,29845,29848,29850,29852,29854],{"class":3834,"line":3922},[3832,29846,29847],{"class":3853},"        [notesApi.reducerPath]:",[3832,29849,29294],{"class":3853},[3832,29851,4183],{"class":3849},[3832,29853,9584],{"class":3853},[3832,29855,4072],{"class":3849},[3832,29857,29858],{"class":3834,"line":3932},[3832,29859,4560],{"class":3849},[3832,29861,29862,29864,29866,29868,29870,29872,29874,29877,29879,29881,29883,29885,29887,29889],{"class":3834,"line":3942},[3832,29863,9595],{"class":4117},[3832,29865,4304],{"class":3853},[3832,29867,4307],{"class":3849},[3832,29869,9602],{"class":3853},[3832,29871,4313],{"class":3849},[3832,29873,4140],{"class":3889},[3832,29875,29876],{"class":4117}," getDefaultMiddleware",[3832,29878,9620],{"class":3849},[3832,29880,9623],{"class":4117},[3832,29882,4162],{"class":3849},[3832,29884,29811],{"class":3853},[3832,29886,4183],{"class":3849},[3832,29888,9632],{"class":3853},[3832,29890,5165],{"class":3849},[3832,29892,29893],{"class":3834,"line":3948},[3832,29894,4566],{"class":3849},[3832,29896,29897],{"class":3834,"line":3953},[3832,29898,3877],{"emptyLinePlaceholder":3876},[3832,29900,29901,29903,29905,29907,29909,29911],{"class":3834,"line":3959},[3832,29902,9518],{"class":4117},[3832,29904,4162],{"class":3849},[3832,29906,9656],{"class":3853},[3832,29908,4183],{"class":3849},[3832,29910,4809],{"class":3853},[3832,29912,4168],{"class":3849},[3809,29914,29916,29917],{"id":29915},"крок-3-екран-керування-нотатками-notesscreentsx","Крок 3. Екран керування нотатками ",[3829,29918,29919],{},"NotesScreen.tsx",[3822,29921,29923],{"className":4592,"code":29922,"language":4594,"meta":3827,"style":3827},"\u002F\u002F src\u002Fscreens\u002FNotesScreen.tsx\nimport React, { useState } from 'react'\nimport { View, Text, TextInput, Button, FlatList, ActivityIndicator, RefreshControl, StyleSheet } from 'react-native'\nimport { useGetNotesQuery, useCreateNoteMutation, useDeleteNoteMutation } from '..\u002Fservices\u002FnotesApi'\n\nexport function NotesScreen() {\n    const [title, setTitle] = useState('')\n    const { data: notes, isLoading, isFetching, refetch } = useGetNotesQuery()\n    const [createNote, { isLoading: isCreating }] = useCreateNoteMutation()\n    const [deleteNote] = useDeleteNoteMutation()\n\n    const handleAdd = async () => {\n        if (!title.trim()) return\n        await createNote({ title, body: 'Текст нової нотатки' }).unwrap()\n        setTitle('')\n    }\n\n    if (isLoading) {\n        return (\n            \u003CView style={styles.center}>\n                \u003CActivityIndicator size=\"large\" color=\"#2563eb\" \u002F>\n            \u003C\u002FView>\n        )\n    }\n\n    return (\n        \u003CView style={styles.container}>\n            \u003CText style={styles.header}>Нотатки подорожей\u003C\u002FText>\n\n            \u003CView style={styles.formRow}>\n                \u003CTextInput\n                    style={styles.input}\n                    placeholder=\"Нова нотатка...\"\n                    value={title}\n                    onChangeText={setTitle}\n                \u002F>\n                \u003CButton title={isCreating ? '...' : 'Додати'} onPress={handleAdd} disabled={isCreating} \u002F>\n            \u003C\u002FView>\n\n            \u003CFlatList\n                data={notes}\n                keyExtractor={(item) => String(item.id)}\n                refreshControl={\u003CRefreshControl refreshing={isFetching} onRefresh={refetch} \u002F>}\n                renderItem={({ item }) => (\n                    \u003CView style={styles.noteItem}>\n                        \u003CView style={{ flex: 1 }}>\n                            \u003CText style={styles.noteTitle}>{item.title}\u003C\u002FText>\n                        \u003C\u002FView>\n                        \u003CButton title=\"🗑️\" color=\"#dc2626\" onPress={() => deleteNote(item.id)} \u002F>\n                    \u003C\u002FView>\n                )}\n            \u002F>\n        \u003C\u002FView>\n    )\n}\n\nconst styles = StyleSheet.create({\n    container: { flex: 1, padding: 16, backgroundColor: '#f1f5f9' },\n    center: { flex: 1, justifyContent: 'center', alignItems: 'center' },\n    header: { fontSize: 22, fontWeight: '800', marginBottom: 16, color: '#0f172a' },\n    formRow: { flexDirection: 'row', gap: 8, marginBottom: 16 },\n    input: { flex: 1, backgroundColor: '#ffffff', padding: 12, borderRadius: 8, borderWidth: 1, borderColor: '#cbd5e1' },\n    noteItem: {\n        flexDirection: 'row',\n        alignItems: 'center',\n        backgroundColor: '#ffffff',\n        padding: 14,\n        borderRadius: 10,\n        marginBottom: 8,\n    },\n    noteTitle: { fontSize: 14, fontWeight: '600', color: '#1e293b' },\n})\n",[3829,29924,29925,29930,29946,29988,30011,30015,30026,30048,30079,30103,30118,30122,30139,30157,30181,30192,30196,30200,30210,30216,30238,30259,30267,30271,30275,30279,30285,30307,30339,30343,30366,30372,30389,30399,30412,30425,30430,30479,30487,30491,30497,30509,30540,30578,30596,30619,30645,30685,30694,30741,30750,30757,30761,30769,30773,30777,30781,30797,30823,30849,30886,30914,30961,30968,30977,30985,30993,31001,31009,31017,31021,31048],{"__ignoreMap":3827},[3832,29926,29927],{"class":3834,"line":3835},[3832,29928,29929],{"class":3838},"\u002F\u002F src\u002Fscreens\u002FNotesScreen.tsx\n",[3832,29931,29932,29934,29936,29938,29940,29942,29944],{"class":3834,"line":3842},[3832,29933,3846],{"class":3845},[3832,29935,4608],{"class":3853},[3832,29937,4611],{"class":3849},[3832,29939,7440],{"class":3853},[3832,29941,3863],{"class":3849},[3832,29943,3866],{"class":3845},[3832,29945,4621],{"class":3869},[3832,29947,29948,29950,29952,29954,29956,29958,29960,29962,29964,29966,29968,29970,29972,29974,29976,29978,29980,29982,29984,29986],{"class":3834,"line":3873},[3832,29949,3846],{"class":3845},[3832,29951,3850],{"class":3849},[3832,29953,4630],{"class":3853},[3832,29955,3857],{"class":3849},[3832,29957,4635],{"class":3853},[3832,29959,3857],{"class":3849},[3832,29961,7535],{"class":3853},[3832,29963,3857],{"class":3849},[3832,29965,18725],{"class":3853},[3832,29967,3857],{"class":3849},[3832,29969,4640],{"class":3853},[3832,29971,3857],{"class":3849},[3832,29973,4645],{"class":3853},[3832,29975,3857],{"class":3849},[3832,29977,18431],{"class":3853},[3832,29979,3857],{"class":3849},[3832,29981,9868],{"class":3853},[3832,29983,3863],{"class":3849},[3832,29985,3866],{"class":3845},[3832,29987,4652],{"class":3869},[3832,29989,29990,29992,29994,29996,29998,30000,30002,30004,30006,30008],{"class":3834,"line":3880},[3832,29991,3846],{"class":3845},[3832,29993,3850],{"class":3849},[3832,29995,29746],{"class":3853},[3832,29997,3857],{"class":3849},[3832,29999,29751],{"class":3853},[3832,30001,3857],{"class":3849},[3832,30003,29756],{"class":3853},[3832,30005,3863],{"class":3849},[3832,30007,3866],{"class":3845},[3832,30009,30010],{"class":3869}," '..\u002Fservices\u002FnotesApi'\n",[3832,30012,30013],{"class":3834,"line":3886},[3832,30014,3877],{"emptyLinePlaceholder":3876},[3832,30016,30017,30019,30021,30024],{"class":3834,"line":3900},[3832,30018,4105],{"class":3845},[3832,30020,4699],{"class":3889},[3832,30022,30023],{"class":4117}," NotesScreen",[3832,30025,4705],{"class":3849},[3832,30027,30028,30030,30032,30034,30036,30038,30040,30042,30044,30046],{"class":3834,"line":3912},[3832,30029,4710],{"class":3889},[3832,30031,6274],{"class":3849},[3832,30033,4998],{"class":4042},[3832,30035,3857],{"class":3849},[3832,30037,7434],{"class":4042},[3832,30039,7437],{"class":3849},[3832,30041,7440],{"class":4117},[3832,30043,4162],{"class":3849},[3832,30045,7445],{"class":3869},[3832,30047,4168],{"class":3849},[3832,30049,30050,30052,30054,30056,30058,30061,30063,30065,30067,30069,30071,30073,30075,30077],{"class":3834,"line":3922},[3832,30051,4710],{"class":3889},[3832,30053,3850],{"class":3849},[3832,30055,6565],{"class":3853},[3832,30057,3906],{"class":3849},[3832,30059,30060],{"class":4042},"notes",[3832,30062,3857],{"class":3849},[3832,30064,4371],{"class":4042},[3832,30066,3857],{"class":3849},[3832,30068,9744],{"class":4042},[3832,30070,3857],{"class":3849},[3832,30072,18336],{"class":4042},[3832,30074,4748],{"class":3849},[3832,30076,29746],{"class":4117},[3832,30078,4230],{"class":3849},[3832,30080,30081,30083,30085,30088,30090,30092,30094,30097,30099,30101],{"class":3834,"line":3932},[3832,30082,4710],{"class":3889},[3832,30084,6274],{"class":3849},[3832,30086,30087],{"class":4042},"createNote",[3832,30089,4611],{"class":3849},[3832,30091,4371],{"class":3853},[3832,30093,3906],{"class":3849},[3832,30095,30096],{"class":4042},"isCreating",[3832,30098,19279],{"class":3849},[3832,30100,29751],{"class":4117},[3832,30102,4230],{"class":3849},[3832,30104,30105,30107,30109,30112,30114,30116],{"class":3834,"line":3942},[3832,30106,4710],{"class":3889},[3832,30108,6274],{"class":3849},[3832,30110,30111],{"class":4042},"deleteNote",[3832,30113,7437],{"class":3849},[3832,30115,29756],{"class":4117},[3832,30117,4230],{"class":3849},[3832,30119,30120],{"class":3834,"line":3948},[3832,30121,3877],{"emptyLinePlaceholder":3876},[3832,30123,30124,30126,30129,30131,30133,30135,30137],{"class":3834,"line":3953},[3832,30125,4710],{"class":3889},[3832,30127,30128],{"class":4117}," handleAdd",[3832,30130,4114],{"class":3849},[3832,30132,5477],{"class":3889},[3832,30134,4137],{"class":3849},[3832,30136,4140],{"class":3889},[3832,30138,3897],{"class":3849},[3832,30140,30141,30143,30145,30147,30149,30151,30154],{"class":3834,"line":3959},[3832,30142,4174],{"class":3845},[3832,30144,4177],{"class":3849},[3832,30146,4998],{"class":3853},[3832,30148,4183],{"class":3849},[3832,30150,17732],{"class":4117},[3832,30152,30153],{"class":3849},"()) ",[3832,30155,30156],{"class":3845},"return\n",[3832,30158,30159,30161,30164,30166,30168,30170,30172,30175,30177,30179],{"class":3834,"line":3969},[3832,30160,23121],{"class":3845},[3832,30162,30163],{"class":4117}," createNote",[3832,30165,4976],{"class":3849},[3832,30167,4998],{"class":3853},[3832,30169,3857],{"class":3849},[3832,30171,24935],{"class":3853},[3832,30173,30174],{"class":3869}," 'Текст нової нотатки'",[3832,30176,23130],{"class":3849},[3832,30178,20520],{"class":4117},[3832,30180,4230],{"class":3849},[3832,30182,30183,30186,30188,30190],{"class":3834,"line":3986},[3832,30184,30185],{"class":4117},"        setTitle",[3832,30187,4162],{"class":3849},[3832,30189,7445],{"class":3869},[3832,30191,4168],{"class":3849},[3832,30193,30194],{"class":3834,"line":4000},[3832,30195,4236],{"class":3849},[3832,30197,30198],{"class":3834,"line":4020},[3832,30199,3877],{"emptyLinePlaceholder":3876},[3832,30201,30202,30204,30206,30208],{"class":3834,"line":4025},[3832,30203,4821],{"class":3845},[3832,30205,4307],{"class":3849},[3832,30207,4371],{"class":3853},[3832,30209,4189],{"class":3849},[3832,30211,30212,30214],{"class":3834,"line":4030},[3832,30213,4220],{"class":3845},[3832,30215,4914],{"class":3849},[3832,30217,30218,30220,30222,30224,30226,30228,30230,30232,30234,30236],{"class":3834,"line":4036},[3832,30219,7532],{"class":4834},[3832,30221,4630],{"class":3893},[3832,30223,8467],{"class":4840},[3832,30225,4844],{"class":3849},[3832,30227,4885],{"class":3889},[3832,30229,9970],{"class":3853},[3832,30231,4183],{"class":4947},[3832,30233,9975],{"class":3853},[3832,30235,4890],{"class":3889},[3832,30237,4898],{"class":4834},[3832,30239,30240,30242,30244,30246,30248,30250,30252,30254,30257],{"class":3834,"line":4054},[3832,30241,9984],{"class":4834},[3832,30243,4645],{"class":3893},[3832,30245,4841],{"class":4840},[3832,30247,4844],{"class":3849},[3832,30249,4847],{"class":3869},[3832,30251,9995],{"class":4840},[3832,30253,4844],{"class":3849},[3832,30255,30256],{"class":3869},"\"#2563eb\"",[3832,30258,4850],{"class":4834},[3832,30260,30261,30263,30265],{"class":3834,"line":4063},[3832,30262,10039],{"class":4834},[3832,30264,4630],{"class":3893},[3832,30266,4898],{"class":4834},[3832,30268,30269],{"class":3834,"line":4075},[3832,30270,10048],{"class":3849},[3832,30272,30273],{"class":3834,"line":4086},[3832,30274,4236],{"class":3849},[3832,30276,30277],{"class":3834,"line":4091},[3832,30278,3877],{"emptyLinePlaceholder":3876},[3832,30280,30281,30283],{"class":3834,"line":4096},[3832,30282,4911],{"class":3845},[3832,30284,4914],{"class":3849},[3832,30286,30287,30289,30291,30293,30295,30297,30299,30301,30303,30305],{"class":3834,"line":4102},[3832,30288,4919],{"class":4834},[3832,30290,4630],{"class":3893},[3832,30292,8467],{"class":4840},[3832,30294,4844],{"class":3849},[3832,30296,4885],{"class":3889},[3832,30298,9970],{"class":3853},[3832,30300,4183],{"class":4947},[3832,30302,18796],{"class":3853},[3832,30304,4890],{"class":3889},[3832,30306,4898],{"class":4834},[3832,30308,30309,30311,30313,30315,30317,30319,30321,30323,30326,30328,30330,30333,30335,30337],{"class":3834,"line":4123},[3832,30310,7532],{"class":4834},[3832,30312,4635],{"class":3893},[3832,30314,8467],{"class":4840},[3832,30316,4844],{"class":3849},[3832,30318,4885],{"class":3889},[3832,30320,9970],{"class":3853},[3832,30322,4183],{"class":4947},[3832,30324,30325],{"class":3853},"header",[3832,30327,4890],{"class":3889},[3832,30329,4879],{"class":4834},[3832,30331,30332],{"class":3849},"Нотатки подорожей",[3832,30334,4893],{"class":4834},[3832,30336,4635],{"class":3893},[3832,30338,4898],{"class":4834},[3832,30340,30341],{"class":3834,"line":4131},[3832,30342,3877],{"emptyLinePlaceholder":3876},[3832,30344,30345,30347,30349,30351,30353,30355,30357,30359,30362,30364],{"class":3834,"line":4145},[3832,30346,7532],{"class":4834},[3832,30348,4630],{"class":3893},[3832,30350,8467],{"class":4840},[3832,30352,4844],{"class":3849},[3832,30354,4885],{"class":3889},[3832,30356,9970],{"class":3853},[3832,30358,4183],{"class":4947},[3832,30360,30361],{"class":3853},"formRow",[3832,30363,4890],{"class":3889},[3832,30365,4898],{"class":4834},[3832,30367,30368,30370],{"class":3834,"line":4171},[3832,30369,9984],{"class":4834},[3832,30371,17051],{"class":3893},[3832,30373,30374,30377,30379,30381,30383,30385,30387],{"class":3834,"line":4192},[3832,30375,30376],{"class":4840},"                    style",[3832,30378,4844],{"class":3849},[3832,30380,4885],{"class":3889},[3832,30382,9970],{"class":3853},[3832,30384,4183],{"class":4947},[3832,30386,20694],{"class":3853},[3832,30388,3945],{"class":3889},[3832,30390,30391,30394,30396],{"class":3834,"line":4211},[3832,30392,30393],{"class":4840},"                    placeholder",[3832,30395,4844],{"class":3849},[3832,30397,30398],{"class":3869},"\"Нова нотатка...\"\n",[3832,30400,30401,30404,30406,30408,30410],{"class":3834,"line":4217},[3832,30402,30403],{"class":4840},"                    value",[3832,30405,4844],{"class":3849},[3832,30407,4885],{"class":3889},[3832,30409,4998],{"class":3853},[3832,30411,3945],{"class":3889},[3832,30413,30414,30417,30419,30421,30423],{"class":3834,"line":4233},[3832,30415,30416],{"class":4840},"                    onChangeText",[3832,30418,4844],{"class":3849},[3832,30420,4885],{"class":3889},[3832,30422,7434],{"class":3853},[3832,30424,3945],{"class":3889},[3832,30426,30427],{"class":3834,"line":4239},[3832,30428,30429],{"class":4834},"                \u002F>\n",[3832,30431,30432,30434,30436,30438,30440,30442,30444,30446,30449,30451,30454,30456,30458,30460,30462,30465,30467,30469,30471,30473,30475,30477],{"class":3834,"line":4244},[3832,30433,9984],{"class":4834},[3832,30435,18725],{"class":3893},[3832,30437,18728],{"class":4840},[3832,30439,4844],{"class":3849},[3832,30441,4885],{"class":3889},[3832,30443,30096],{"class":3853},[3832,30445,8488],{"class":3849},[3832,30447,30448],{"class":3869}," '...'",[3832,30450,8494],{"class":3849},[3832,30452,30453],{"class":3869}," 'Додати'",[3832,30455,4890],{"class":3889},[3832,30457,18736],{"class":4840},[3832,30459,4844],{"class":3849},[3832,30461,4885],{"class":3889},[3832,30463,30464],{"class":3853},"handleAdd",[3832,30466,4890],{"class":3889},[3832,30468,21546],{"class":4840},[3832,30470,4844],{"class":3849},[3832,30472,4885],{"class":3889},[3832,30474,30096],{"class":3853},[3832,30476,4890],{"class":3889},[3832,30478,4850],{"class":4834},[3832,30480,30481,30483,30485],{"class":3834,"line":4249},[3832,30482,10039],{"class":4834},[3832,30484,4630],{"class":3893},[3832,30486,4898],{"class":4834},[3832,30488,30489],{"class":3834,"line":4255},[3832,30490,3877],{"emptyLinePlaceholder":3876},[3832,30492,30493,30495],{"class":3834,"line":4270},[3832,30494,7532],{"class":4834},[3832,30496,4922],{"class":3893},[3832,30498,30499,30501,30503,30505,30507],{"class":3834,"line":4281},[3832,30500,17103],{"class":4840},[3832,30502,4844],{"class":3849},[3832,30504,4885],{"class":3889},[3832,30506,30060],{"class":3853},[3832,30508,3945],{"class":3889},[3832,30510,30511,30513,30515,30517,30519,30521,30523,30525,30528,30530,30532,30534,30536,30538],{"class":3834,"line":4289},[3832,30512,18937],{"class":4840},[3832,30514,4844],{"class":3849},[3832,30516,4885],{"class":3889},[3832,30518,4162],{"class":4947},[3832,30520,4950],{"class":3853},[3832,30522,4313],{"class":4947},[3832,30524,4140],{"class":3889},[3832,30526,30527],{"class":4117}," String",[3832,30529,4162],{"class":4947},[3832,30531,4950],{"class":3853},[3832,30533,4183],{"class":4947},[3832,30535,4962],{"class":3853},[3832,30537,9460],{"class":4947},[3832,30539,3945],{"class":3889},[3832,30541,30542,30544,30546,30548,30550,30552,30555,30557,30559,30561,30563,30566,30568,30570,30572,30574,30576],{"class":3834,"line":4298},[3832,30543,19010],{"class":4840},[3832,30545,4844],{"class":3849},[3832,30547,4885],{"class":3889},[3832,30549,5084],{"class":4834},[3832,30551,18431],{"class":3893},[3832,30553,30554],{"class":4840}," refreshing",[3832,30556,4844],{"class":3849},[3832,30558,4885],{"class":3889},[3832,30560,9744],{"class":3853},[3832,30562,4890],{"class":3889},[3832,30564,30565],{"class":4840}," onRefresh",[3832,30567,4844],{"class":3849},[3832,30569,4885],{"class":3889},[3832,30571,18336],{"class":3853},[3832,30573,4890],{"class":3889},[3832,30575,17147],{"class":4834},[3832,30577,3945],{"class":3889},[3832,30579,30580,30582,30584,30586,30588,30590,30592,30594],{"class":3834,"line":4320},[3832,30581,17116],{"class":4840},[3832,30583,4844],{"class":3849},[3832,30585,4885],{"class":3889},[3832,30587,4976],{"class":4947},[3832,30589,4950],{"class":3853},[3832,30591,4981],{"class":4947},[3832,30593,4140],{"class":3889},[3832,30595,4914],{"class":4947},[3832,30597,30598,30600,30602,30604,30606,30608,30610,30612,30615,30617],{"class":3834,"line":4326},[3832,30599,10274],{"class":4834},[3832,30601,4630],{"class":3893},[3832,30603,8467],{"class":4840},[3832,30605,4844],{"class":3849},[3832,30607,4885],{"class":3889},[3832,30609,9970],{"class":3853},[3832,30611,4183],{"class":4947},[3832,30613,30614],{"class":3853},"noteItem",[3832,30616,4890],{"class":3889},[3832,30618,4898],{"class":4834},[3832,30620,30621,30624,30626,30628,30630,30632,30634,30637,30639,30641,30643],{"class":3834,"line":4332},[3832,30622,30623],{"class":4834},"                        \u003C",[3832,30625,4630],{"class":3893},[3832,30627,8467],{"class":4840},[3832,30629,4844],{"class":3849},[3832,30631,4885],{"class":3889},[3832,30633,8474],{"class":4947},[3832,30635,30636],{"class":3853},"flex:",[3832,30638,10411],{"class":5726},[3832,30640,8500],{"class":4947},[3832,30642,4890],{"class":3889},[3832,30644,4898],{"class":4834},[3832,30646,30647,30650,30652,30654,30656,30658,30660,30662,30665,30667,30669,30671,30673,30675,30677,30679,30681,30683],{"class":3834,"line":4363},[3832,30648,30649],{"class":4834},"                            \u003C",[3832,30651,4635],{"class":3893},[3832,30653,8467],{"class":4840},[3832,30655,4844],{"class":3849},[3832,30657,4885],{"class":3889},[3832,30659,9970],{"class":3853},[3832,30661,4183],{"class":4947},[3832,30663,30664],{"class":3853},"noteTitle",[3832,30666,4890],{"class":3889},[3832,30668,4879],{"class":4834},[3832,30670,4885],{"class":3889},[3832,30672,4950],{"class":3853},[3832,30674,4183],{"class":4947},[3832,30676,4998],{"class":3853},[3832,30678,4890],{"class":3889},[3832,30680,4893],{"class":4834},[3832,30682,4635],{"class":3893},[3832,30684,4898],{"class":4834},[3832,30686,30687,30690,30692],{"class":3834,"line":4379},[3832,30688,30689],{"class":4834},"                        \u003C\u002F",[3832,30691,4630],{"class":3893},[3832,30693,4898],{"class":4834},[3832,30695,30696,30698,30700,30702,30704,30707,30709,30711,30714,30716,30718,30720,30722,30724,30727,30729,30731,30733,30735,30737,30739],{"class":3834,"line":4394},[3832,30697,30623],{"class":4834},[3832,30699,18725],{"class":3893},[3832,30701,18728],{"class":4840},[3832,30703,4844],{"class":3849},[3832,30705,30706],{"class":3869},"\"🗑️\"",[3832,30708,9995],{"class":4840},[3832,30710,4844],{"class":3849},[3832,30712,30713],{"class":3869},"\"#dc2626\"",[3832,30715,18736],{"class":4840},[3832,30717,4844],{"class":3849},[3832,30719,4885],{"class":3889},[3832,30721,11455],{"class":4947},[3832,30723,4140],{"class":3889},[3832,30725,30726],{"class":4117}," deleteNote",[3832,30728,4162],{"class":4947},[3832,30730,4950],{"class":3853},[3832,30732,4183],{"class":4947},[3832,30734,4962],{"class":3853},[3832,30736,9460],{"class":4947},[3832,30738,4890],{"class":3889},[3832,30740,4850],{"class":4834},[3832,30742,30743,30746,30748],{"class":3834,"line":4400},[3832,30744,30745],{"class":4834},"                    \u003C\u002F",[3832,30747,4630],{"class":3893},[3832,30749,4898],{"class":4834},[3832,30751,30752,30755],{"class":3834,"line":4406},[3832,30753,30754],{"class":4947},"                )",[3832,30756,3945],{"class":3889},[3832,30758,30759],{"class":3834,"line":4437},[3832,30760,7581],{"class":4834},[3832,30762,30763,30765,30767],{"class":3834,"line":4451},[3832,30764,7596],{"class":4834},[3832,30766,4630],{"class":3893},[3832,30768,4898],{"class":4834},[3832,30770,30771],{"class":3834,"line":4470},[3832,30772,5018],{"class":3849},[3832,30774,30775],{"class":3834,"line":4475},[3832,30776,3945],{"class":3849},[3832,30778,30779],{"class":3834,"line":4481},[3832,30780,3877],{"emptyLinePlaceholder":3876},[3832,30782,30783,30785,30787,30789,30791,30793,30795],{"class":3834,"line":4511},[3832,30784,4039],{"class":3889},[3832,30786,10385],{"class":4042},[3832,30788,4114],{"class":3849},[3832,30790,9868],{"class":3853},[3832,30792,4183],{"class":3849},[3832,30794,10394],{"class":4117},[3832,30796,4267],{"class":3849},[3832,30798,30799,30802,30804,30806,30808,30810,30812,30814,30816,30818,30821],{"class":3834,"line":4524},[3832,30800,30801],{"class":3853},"    container:",[3832,30803,3850],{"class":3849},[3832,30805,30636],{"class":3853},[3832,30807,10411],{"class":5726},[3832,30809,3857],{"class":3849},[3832,30811,20632],{"class":3853},[3832,30813,10500],{"class":5726},[3832,30815,3857],{"class":3849},[3832,30817,8477],{"class":3853},[3832,30819,30820],{"class":3869}," '#f1f5f9'",[3832,30822,5145],{"class":3849},[3832,30824,30825,30827,30829,30831,30833,30835,30838,30840,30842,30845,30847],{"class":3834,"line":4552},[3832,30826,10401],{"class":3853},[3832,30828,3850],{"class":3849},[3832,30830,30636],{"class":3853},[3832,30832,10411],{"class":5726},[3832,30834,3857],{"class":3849},[3832,30836,30837],{"class":3853},"justifyContent:",[3832,30839,10421],{"class":3869},[3832,30841,3857],{"class":3849},[3832,30843,30844],{"class":3853},"alignItems:",[3832,30846,10421],{"class":3869},[3832,30848,5145],{"class":3849},[3832,30850,30851,30854,30856,30859,30862,30864,30867,30870,30872,30875,30877,30879,30882,30884],{"class":3834,"line":4557},[3832,30852,30853],{"class":3853},"    header:",[3832,30855,3850],{"class":3849},[3832,30857,30858],{"class":3853},"fontSize:",[3832,30860,30861],{"class":5726}," 22",[3832,30863,3857],{"class":3849},[3832,30865,30866],{"class":3853},"fontWeight:",[3832,30868,30869],{"class":3869}," '800'",[3832,30871,3857],{"class":3849},[3832,30873,30874],{"class":3853},"marginBottom:",[3832,30876,10500],{"class":5726},[3832,30878,3857],{"class":3849},[3832,30880,30881],{"class":3853},"color:",[3832,30883,10688],{"class":3869},[3832,30885,5145],{"class":3849},[3832,30887,30888,30891,30893,30896,30899,30901,30904,30906,30908,30910,30912],{"class":3834,"line":4563},[3832,30889,30890],{"class":3853},"    formRow:",[3832,30892,3850],{"class":3849},[3832,30894,30895],{"class":3853},"flexDirection:",[3832,30897,30898],{"class":3869}," 'row'",[3832,30900,3857],{"class":3849},[3832,30902,30903],{"class":3853},"gap:",[3832,30905,10699],{"class":5726},[3832,30907,3857],{"class":3849},[3832,30909,30874],{"class":3853},[3832,30911,10500],{"class":5726},[3832,30913,5145],{"class":3849},[3832,30915,30916,30919,30921,30923,30925,30927,30929,30931,30933,30935,30937,30939,30942,30944,30946,30949,30951,30953,30956,30959],{"class":3834,"line":4569},[3832,30917,30918],{"class":3853},"    input:",[3832,30920,3850],{"class":3849},[3832,30922,30636],{"class":3853},[3832,30924,10411],{"class":5726},[3832,30926,3857],{"class":3849},[3832,30928,8477],{"class":3853},[3832,30930,10540],{"class":3869},[3832,30932,3857],{"class":3849},[3832,30934,20632],{"class":3853},[3832,30936,10461],{"class":5726},[3832,30938,3857],{"class":3849},[3832,30940,30941],{"class":3853},"borderRadius:",[3832,30943,10699],{"class":5726},[3832,30945,3857],{"class":3849},[3832,30947,30948],{"class":3853},"borderWidth:",[3832,30950,10411],{"class":5726},[3832,30952,3857],{"class":3849},[3832,30954,30955],{"class":3853},"borderColor:",[3832,30957,30958],{"class":3869}," '#cbd5e1'",[3832,30960,5145],{"class":3849},[3832,30962,30963,30966],{"class":3834,"line":4574},[3832,30964,30965],{"class":3853},"    noteItem:",[3832,30967,3897],{"class":3849},[3832,30969,30970,30973,30975],{"class":3834,"line":10534},[3832,30971,30972],{"class":3853},"        flexDirection:",[3832,30974,30898],{"class":3869},[3832,30976,4072],{"class":3849},[3832,30978,30979,30981,30983],{"class":3834,"line":10545},[3832,30980,10428],{"class":3853},[3832,30982,10421],{"class":3869},[3832,30984,4072],{"class":3849},[3832,30986,30987,30989,30991],{"class":3834,"line":10554},[3832,30988,10537],{"class":3853},[3832,30990,10540],{"class":3869},[3832,30992,4072],{"class":3849},[3832,30994,30995,30997,30999],{"class":3834,"line":10564},[3832,30996,10437],{"class":3853},[3832,30998,10470],{"class":5726},[3832,31000,4072],{"class":3849},[3832,31002,31003,31005,31007],{"class":3834,"line":10573},[3832,31004,10576],{"class":3853},[3832,31006,17232],{"class":5726},[3832,31008,4072],{"class":3849},[3832,31010,31011,31013,31015],{"class":3834,"line":10583},[3832,31012,10696],{"class":3853},[3832,31014,10699],{"class":5726},[3832,31016,4072],{"class":3849},[3832,31018,31019],{"class":3834,"line":10593},[3832,31020,4560],{"class":3849},[3832,31022,31023,31026,31028,31030,31032,31034,31036,31039,31041,31043,31046],{"class":3834,"line":10617},[3832,31024,31025],{"class":3853},"    noteTitle:",[3832,31027,3850],{"class":3849},[3832,31029,30858],{"class":3853},[3832,31031,10470],{"class":5726},[3832,31033,3857],{"class":3849},[3832,31035,30866],{"class":3853},[3832,31037,31038],{"class":3869}," '600'",[3832,31040,3857],{"class":3849},[3832,31042,30881],{"class":3853},[3832,31044,31045],{"class":3869}," '#1e293b'",[3832,31047,5145],{"class":3849},[3832,31049,31050],{"class":3834,"line":10628},[3832,31051,4566],{"class":3849},[3793,31053],{},[3796,31055,31057],{"id":31056},"наскрізний-проєкт-nomad-міграція-на-rtk-query","Наскрізний проєкт: Nomad — міграція на RTK Query",[3801,31059,31060,31061,18007,31064,31067,31068,4183],{},"Тепер замінимо застарілий ручний ",[3829,31062,31063],{},"tripsSlice",[3829,31065,31066],{},"fetchTripsThunk"," у додатку Nomad на сучасний декларативний сервіс ",[3829,31069,24368],{},[3809,31071,31073,31074],{"id":31072},"_1-повний-сервіс-srcservicestripsapits","1. Повний сервіс ",[3829,31075,31076],{},"src\u002Fservices\u002FtripsApi.ts",[3822,31078,31080],{"className":3824,"code":31079,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fservices\u002FtripsApi.ts\nimport { createApi, fetchBaseQuery } from '@reduxjs\u002Ftoolkit\u002Fquery\u002Freact'\nimport { Platform } from 'react-native'\nimport Constants from 'expo-constants'\n\nexport interface Trip {\n    id: string\n    title: string\n    region: string\n    startDate: string\n    endDate: string | null\n    description: string | null\n    isFavorite?: boolean\n}\n\nexport interface CreateTripPayload {\n    title: string\n    region: string\n    startDate: string\n    endDate?: string | null\n    description?: string | null\n}\n\nconst getBaseUrl = (): string => {\n    if (Platform.OS === 'android') return 'http:\u002F\u002F10.0.2.2:3000'\n    const hostUri = Constants.expoConfig?.hostUri\n    if (hostUri) {\n        const ip = hostUri.split(':').shift()\n        if (ip) return `http:\u002F\u002F${ip}:3000`\n    }\n    return 'http:\u002F\u002Flocalhost:3000'\n}\n\nexport const tripsApi = createApi({\n    reducerPath: 'tripsApi',\n    baseQuery: fetchBaseQuery({ baseUrl: getBaseUrl(), timeout: 8000 }),\n    tagTypes: ['Trip'],\n    refetchOnFocus: true,\n    refetchOnReconnect: true,\n    endpoints: (builder) => ({\n        getTrips: builder.query\u003CTrip[], void>({\n            query: () => '\u002Ftrips',\n            providesTags: (result) =>\n                result\n                    ? [...result.map(({ id }) => ({ type: 'Trip' as const, id })), { type: 'Trip', id: 'LIST' }]\n                    : [{ type: 'Trip', id: 'LIST' }],\n        }),\n\n        getTripById: builder.query\u003CTrip, string>({\n            query: (id) => `\u002Ftrips\u002F${id}`,\n            providesTags: (_result, _error, id) => [{ type: 'Trip', id }],\n        }),\n\n        createTrip: builder.mutation\u003CTrip, CreateTripPayload>({\n            query: (payload) => ({\n                url: '\u002Ftrips',\n                method: 'POST',\n                body: payload,\n            }),\n            invalidatesTags: [{ type: 'Trip', id: 'LIST' }],\n        }),\n    }),\n})\n\nexport const { useGetTripsQuery, useGetTripByIdQuery, useCreateTripMutation } = tripsApi\n",[3829,31081,31082,31086,31104,31118,31128,31132,31142,31150,31158,31166,31174,31187,31200,31209,31213,31217,31228,31236,31244,31252,31264,31276,31280,31284,31298,31320,31338,31348,31372,31394,31398,31404,31408,31412,31426,31434,31457,31467,31475,31483,31499,31519,31533,31547,31551,31597,31613,31617,31621,31641,31667,31701,31705,31709,31730,31746,31754,31762,31771,31775,31793,31797,31801,31805,31809],{"__ignoreMap":3827},[3832,31083,31084],{"class":3834,"line":3835},[3832,31085,11022],{"class":3838},[3832,31087,31088,31090,31092,31094,31096,31098,31100,31102],{"class":3834,"line":3842},[3832,31089,3846],{"class":3845},[3832,31091,3850],{"class":3849},[3832,31093,6153],{"class":3853},[3832,31095,3857],{"class":3849},[3832,31097,6158],{"class":3853},[3832,31099,3863],{"class":3849},[3832,31101,3866],{"class":3845},[3832,31103,6165],{"class":3869},[3832,31105,31106,31108,31110,31112,31114,31116],{"class":3834,"line":3873},[3832,31107,3846],{"class":3845},[3832,31109,3850],{"class":3849},[3832,31111,11049],{"class":3853},[3832,31113,3863],{"class":3849},[3832,31115,3866],{"class":3845},[3832,31117,4652],{"class":3869},[3832,31119,31120,31122,31124,31126],{"class":3834,"line":3880},[3832,31121,3846],{"class":3845},[3832,31123,11062],{"class":3853},[3832,31125,5856],{"class":3845},[3832,31127,11067],{"class":3869},[3832,31129,31130],{"class":3834,"line":3886},[3832,31131,3877],{"emptyLinePlaceholder":3876},[3832,31133,31134,31136,31138,31140],{"class":3834,"line":3900},[3832,31135,4105],{"class":3845},[3832,31137,28752],{"class":3889},[3832,31139,3894],{"class":3893},[3832,31141,3897],{"class":3849},[3832,31143,31144,31146,31148],{"class":3834,"line":3912},[3832,31145,3903],{"class":3853},[3832,31147,3906],{"class":3849},[3832,31149,3909],{"class":3893},[3832,31151,31152,31154,31156],{"class":3834,"line":3922},[3832,31153,3915],{"class":3853},[3832,31155,3906],{"class":3849},[3832,31157,3909],{"class":3893},[3832,31159,31160,31162,31164],{"class":3834,"line":3932},[3832,31161,3925],{"class":3853},[3832,31163,3906],{"class":3849},[3832,31165,3909],{"class":3893},[3832,31167,31168,31170,31172],{"class":3834,"line":3942},[3832,31169,3935],{"class":3853},[3832,31171,3906],{"class":3849},[3832,31173,3909],{"class":3893},[3832,31175,31176,31179,31181,31183,31185],{"class":3834,"line":3948},[3832,31177,31178],{"class":3853},"    endDate",[3832,31180,3906],{"class":3849},[3832,31182,4008],{"class":3893},[3832,31184,4011],{"class":3849},[3832,31186,4391],{"class":3893},[3832,31188,31189,31192,31194,31196,31198],{"class":3834,"line":3953},[3832,31190,31191],{"class":3853},"    description",[3832,31193,3906],{"class":3849},[3832,31195,4008],{"class":3893},[3832,31197,4011],{"class":3849},[3832,31199,4391],{"class":3893},[3832,31201,31202,31205,31207],{"class":3834,"line":3959},[3832,31203,31204],{"class":3853},"    isFavorite",[3832,31206,16378],{"class":3849},[3832,31208,7187],{"class":3893},[3832,31210,31211],{"class":3834,"line":3969},[3832,31212,3945],{"class":3849},[3832,31214,31215],{"class":3834,"line":3986},[3832,31216,3877],{"emptyLinePlaceholder":3876},[3832,31218,31219,31221,31223,31226],{"class":3834,"line":4000},[3832,31220,4105],{"class":3845},[3832,31222,28752],{"class":3889},[3832,31224,31225],{"class":3893}," CreateTripPayload",[3832,31227,3897],{"class":3849},[3832,31229,31230,31232,31234],{"class":3834,"line":4020},[3832,31231,3915],{"class":3853},[3832,31233,3906],{"class":3849},[3832,31235,3909],{"class":3893},[3832,31237,31238,31240,31242],{"class":3834,"line":4025},[3832,31239,3925],{"class":3853},[3832,31241,3906],{"class":3849},[3832,31243,3909],{"class":3893},[3832,31245,31246,31248,31250],{"class":3834,"line":4030},[3832,31247,3935],{"class":3853},[3832,31249,3906],{"class":3849},[3832,31251,3909],{"class":3893},[3832,31253,31254,31256,31258,31260,31262],{"class":3834,"line":4036},[3832,31255,31178],{"class":3853},[3832,31257,16378],{"class":3849},[3832,31259,4008],{"class":3893},[3832,31261,4011],{"class":3849},[3832,31263,4391],{"class":3893},[3832,31265,31266,31268,31270,31272,31274],{"class":3834,"line":4054},[3832,31267,31191],{"class":3853},[3832,31269,16378],{"class":3849},[3832,31271,4008],{"class":3893},[3832,31273,4011],{"class":3849},[3832,31275,4391],{"class":3893},[3832,31277,31278],{"class":3834,"line":4063},[3832,31279,3945],{"class":3849},[3832,31281,31282],{"class":3834,"line":4075},[3832,31283,3877],{"emptyLinePlaceholder":3876},[3832,31285,31286,31288,31290,31292,31294,31296],{"class":3834,"line":4086},[3832,31287,4039],{"class":3889},[3832,31289,11113],{"class":4117},[3832,31291,11116],{"class":3849},[3832,31293,4008],{"class":3893},[3832,31295,11121],{"class":3889},[3832,31297,3897],{"class":3849},[3832,31299,31300,31302,31304,31306,31308,31310,31312,31314,31316,31318],{"class":3834,"line":4091},[3832,31301,4821],{"class":3845},[3832,31303,4307],{"class":3849},[3832,31305,11049],{"class":3853},[3832,31307,4183],{"class":3849},[3832,31309,11141],{"class":4042},[3832,31311,5921],{"class":3849},[3832,31313,11146],{"class":3869},[3832,31315,4313],{"class":3849},[3832,31317,6600],{"class":3845},[3832,31319,11155],{"class":3869},[3832,31321,31322,31324,31326,31328,31330,31332,31334,31336],{"class":3834,"line":4096},[3832,31323,4710],{"class":3889},[3832,31325,11175],{"class":4042},[3832,31327,4114],{"class":3849},[3832,31329,11180],{"class":3853},[3832,31331,4183],{"class":3849},[3832,31333,11185],{"class":3853},[3832,31335,11188],{"class":3849},[3832,31337,11191],{"class":3853},[3832,31339,31340,31342,31344,31346],{"class":3834,"line":4102},[3832,31341,4821],{"class":3845},[3832,31343,4307],{"class":3849},[3832,31345,11200],{"class":3853},[3832,31347,4189],{"class":3849},[3832,31349,31350,31352,31354,31356,31358,31360,31362,31364,31366,31368,31370],{"class":3834,"line":4123},[3832,31351,4148],{"class":3889},[3832,31353,11209],{"class":4042},[3832,31355,4114],{"class":3849},[3832,31357,11200],{"class":3853},[3832,31359,4183],{"class":3849},[3832,31361,11218],{"class":4117},[3832,31363,4162],{"class":3849},[3832,31365,11223],{"class":3869},[3832,31367,5621],{"class":3849},[3832,31369,11228],{"class":4117},[3832,31371,4230],{"class":3849},[3832,31373,31374,31376,31378,31380,31382,31384,31386,31388,31390,31392],{"class":3834,"line":4131},[3832,31375,4174],{"class":3845},[3832,31377,4307],{"class":3849},[3832,31379,11239],{"class":3853},[3832,31381,4313],{"class":3849},[3832,31383,6600],{"class":3845},[3832,31385,11246],{"class":3869},[3832,31387,11249],{"class":3889},[3832,31389,11239],{"class":3853},[3832,31391,4890],{"class":3889},[3832,31393,11256],{"class":3869},[3832,31395,31396],{"class":3834,"line":4145},[3832,31397,4236],{"class":3849},[3832,31399,31400,31402],{"class":3834,"line":4171},[3832,31401,4911],{"class":3845},[3832,31403,11276],{"class":3869},[3832,31405,31406],{"class":3834,"line":4192},[3832,31407,3945],{"class":3849},[3832,31409,31410],{"class":3834,"line":4211},[3832,31411,3877],{"emptyLinePlaceholder":3876},[3832,31413,31414,31416,31418,31420,31422,31424],{"class":3834,"line":4217},[3832,31415,4105],{"class":3845},[3832,31417,4108],{"class":3889},[3832,31419,6231],{"class":4042},[3832,31421,4114],{"class":3849},[3832,31423,6153],{"class":4117},[3832,31425,4267],{"class":3849},[3832,31427,31428,31430,31432],{"class":3834,"line":4233},[3832,31429,6242],{"class":3853},[3832,31431,6245],{"class":3869},[3832,31433,4072],{"class":3849},[3832,31435,31436,31438,31440,31442,31444,31446,31449,31452,31455],{"class":3834,"line":4239},[3832,31437,6252],{"class":3853},[3832,31439,6255],{"class":4117},[3832,31441,4976],{"class":3849},[3832,31443,6260],{"class":3853},[3832,31445,11113],{"class":4117},[3832,31447,31448],{"class":3849},"(), ",[3832,31450,31451],{"class":3853},"timeout:",[3832,31453,31454],{"class":5726}," 8000",[3832,31456,6266],{"class":3849},[3832,31458,31459,31461,31463,31465],{"class":3834,"line":4244},[3832,31460,6271],{"class":3853},[3832,31462,6274],{"class":3849},[3832,31464,6277],{"class":3869},[3832,31466,11605],{"class":3849},[3832,31468,31469,31471,31473],{"class":3834,"line":4249},[3832,31470,11619],{"class":3853},[3832,31472,11622],{"class":3889},[3832,31474,4072],{"class":3849},[3832,31476,31477,31479,31481],{"class":3834,"line":4255},[3832,31478,11638],{"class":3853},[3832,31480,11622],{"class":3889},[3832,31482,4072],{"class":3849},[3832,31484,31485,31487,31489,31491,31493,31495,31497],{"class":3834,"line":4270},[3832,31486,6288],{"class":4117},[3832,31488,4304],{"class":3853},[3832,31490,4307],{"class":3849},[3832,31492,4310],{"class":3853},[3832,31494,4313],{"class":3849},[3832,31496,4140],{"class":3889},[3832,31498,6301],{"class":3849},[3832,31500,31501,31503,31505,31507,31509,31511,31513,31515,31517],{"class":3834,"line":4281},[3832,31502,6311],{"class":3853},[3832,31504,6314],{"class":3853},[3832,31506,4183],{"class":3849},[3832,31508,6319],{"class":4117},[3832,31510,5084],{"class":3849},[3832,31512,3977],{"class":3893},[3832,31514,6326],{"class":3849},[3832,31516,6329],{"class":3893},[3832,31518,6332],{"class":3849},[3832,31520,31521,31523,31525,31527,31529,31531],{"class":3834,"line":4289},[3832,31522,6337],{"class":4117},[3832,31524,4304],{"class":3853},[3832,31526,4137],{"class":3849},[3832,31528,4140],{"class":3889},[3832,31530,6346],{"class":3869},[3832,31532,4072],{"class":3849},[3832,31534,31535,31537,31539,31541,31543,31545],{"class":3834,"line":4298},[3832,31536,25270],{"class":4117},[3832,31538,4304],{"class":3853},[3832,31540,4307],{"class":3849},[3832,31542,13782],{"class":3853},[3832,31544,4313],{"class":3849},[3832,31546,9607],{"class":3889},[3832,31548,31549],{"class":3834,"line":4320},[3832,31550,25285],{"class":3853},[3832,31552,31553,31555,31557,31559,31561,31563,31565,31567,31569,31571,31573,31575,31577,31579,31581,31583,31585,31587,31589,31591,31593,31595],{"class":3834,"line":4326},[3832,31554,26641],{"class":3849},[3832,31556,13782],{"class":3853},[3832,31558,4183],{"class":3849},[3832,31560,17783],{"class":4117},[3832,31562,29418],{"class":3849},[3832,31564,4962],{"class":3853},[3832,31566,4981],{"class":3849},[3832,31568,4140],{"class":3889},[3832,31570,19679],{"class":3849},[3832,31572,21896],{"class":3853},[3832,31574,21899],{"class":3869},[3832,31576,14013],{"class":3845},[3832,31578,4108],{"class":3889},[3832,31580,3857],{"class":3849},[3832,31582,4962],{"class":3853},[3832,31584,29442],{"class":3849},[3832,31586,21896],{"class":3853},[3832,31588,21899],{"class":3869},[3832,31590,3857],{"class":3849},[3832,31592,22383],{"class":3853},[3832,31594,22402],{"class":3869},[3832,31596,25931],{"class":3849},[3832,31598,31599,31601,31603,31605,31607,31609,31611],{"class":3834,"line":4332},[3832,31600,25359],{"class":3849},[3832,31602,21896],{"class":3853},[3832,31604,21899],{"class":3869},[3832,31606,3857],{"class":3849},[3832,31608,22383],{"class":3853},[3832,31610,22402],{"class":3869},[3832,31612,25372],{"class":3849},[3832,31614,31615],{"class":3834,"line":4363},[3832,31616,6367],{"class":3849},[3832,31618,31619],{"class":3834,"line":4379},[3832,31620,3877],{"emptyLinePlaceholder":3876},[3832,31622,31623,31625,31627,31629,31631,31633,31635,31637,31639],{"class":3834,"line":4394},[3832,31624,25390],{"class":3853},[3832,31626,6314],{"class":3853},[3832,31628,4183],{"class":3849},[3832,31630,6319],{"class":4117},[3832,31632,5084],{"class":3849},[3832,31634,3977],{"class":3893},[3832,31636,3857],{"class":3849},[3832,31638,4008],{"class":3893},[3832,31640,6332],{"class":3849},[3832,31642,31643,31645,31647,31649,31651,31653,31655,31657,31659,31661,31663,31665],{"class":3834,"line":4400},[3832,31644,6337],{"class":4117},[3832,31646,4304],{"class":3853},[3832,31648,4307],{"class":3849},[3832,31650,4962],{"class":3853},[3832,31652,4313],{"class":3849},[3832,31654,4140],{"class":3889},[3832,31656,21826],{"class":3869},[3832,31658,11249],{"class":3889},[3832,31660,4962],{"class":3853},[3832,31662,4890],{"class":3889},[3832,31664,11514],{"class":3869},[3832,31666,4072],{"class":3849},[3832,31668,31669,31671,31673,31675,31677,31679,31681,31683,31685,31687,31689,31691,31693,31695,31697,31699],{"class":3834,"line":4406},[3832,31670,25270],{"class":4117},[3832,31672,4304],{"class":3853},[3832,31674,4307],{"class":3849},[3832,31676,21873],{"class":3853},[3832,31678,3857],{"class":3849},[3832,31680,21878],{"class":3853},[3832,31682,3857],{"class":3849},[3832,31684,4962],{"class":3853},[3832,31686,4313],{"class":3849},[3832,31688,4140],{"class":3889},[3832,31690,25457],{"class":3849},[3832,31692,21896],{"class":3853},[3832,31694,21899],{"class":3869},[3832,31696,3857],{"class":3849},[3832,31698,4962],{"class":3853},[3832,31700,25372],{"class":3849},[3832,31702,31703],{"class":3834,"line":4437},[3832,31704,6367],{"class":3849},[3832,31706,31707],{"class":3834,"line":4451},[3832,31708,3877],{"emptyLinePlaceholder":3876},[3832,31710,31711,31713,31715,31717,31719,31721,31723,31725,31728],{"class":3834,"line":4470},[3832,31712,6377],{"class":3853},[3832,31714,6314],{"class":3853},[3832,31716,4183],{"class":3849},[3832,31718,6384],{"class":4117},[3832,31720,5084],{"class":3849},[3832,31722,3977],{"class":3893},[3832,31724,3857],{"class":3849},[3832,31726,31727],{"class":3893},"CreateTripPayload",[3832,31729,6332],{"class":3849},[3832,31731,31732,31734,31736,31738,31740,31742,31744],{"class":3834,"line":4475},[3832,31733,6337],{"class":4117},[3832,31735,4304],{"class":3853},[3832,31737,4307],{"class":3849},[3832,31739,5336],{"class":3853},[3832,31741,4313],{"class":3849},[3832,31743,4140],{"class":3889},[3832,31745,6301],{"class":3849},[3832,31747,31748,31750,31752],{"class":3834,"line":4481},[3832,31749,6424],{"class":3853},[3832,31751,6346],{"class":3869},[3832,31753,4072],{"class":3849},[3832,31755,31756,31758,31760],{"class":3834,"line":4511},[3832,31757,6433],{"class":3853},[3832,31759,5125],{"class":3869},[3832,31761,4072],{"class":3849},[3832,31763,31764,31766,31769],{"class":3834,"line":4524},[3832,31765,6442],{"class":3853},[3832,31767,31768],{"class":3853}," payload",[3832,31770,4072],{"class":3849},[3832,31772,31773],{"class":3834,"line":4552},[3832,31774,6452],{"class":3849},[3832,31776,31777,31779,31781,31783,31785,31787,31789,31791],{"class":3834,"line":4557},[3832,31778,6457],{"class":3853},[3832,31780,25457],{"class":3849},[3832,31782,21896],{"class":3853},[3832,31784,21899],{"class":3869},[3832,31786,3857],{"class":3849},[3832,31788,22383],{"class":3853},[3832,31790,22402],{"class":3869},[3832,31792,25372],{"class":3849},[3832,31794,31795],{"class":3834,"line":4563},[3832,31796,6367],{"class":3849},[3832,31798,31799],{"class":3834,"line":4569},[3832,31800,6475],{"class":3849},[3832,31802,31803],{"class":3834,"line":4574},[3832,31804,4566],{"class":3849},[3832,31806,31807],{"class":3834,"line":10534},[3832,31808,3877],{"emptyLinePlaceholder":3876},[3832,31810,31811,31813,31815,31817,31819,31821,31823,31825,31827,31829],{"class":3834,"line":10545},[3832,31812,4105],{"class":3845},[3832,31814,4108],{"class":3889},[3832,31816,3850],{"class":3849},[3832,31818,6499],{"class":4042},[3832,31820,3857],{"class":3849},[3832,31822,8328],{"class":4042},[3832,31824,3857],{"class":3849},[3832,31826,6504],{"class":4042},[3832,31828,4748],{"class":3849},[3832,31830,6509],{"class":3853},[3809,31832,31834],{"id":31833},"_2-оновлення-кореневого-store","2. Оновлення кореневого Store",[3822,31836,31838],{"className":3824,"code":31837,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fstore\u002Findex.ts\nimport { configureStore } from '@reduxjs\u002Ftoolkit'\nimport { setupListeners } from '@reduxjs\u002Ftoolkit\u002Fquery'\nimport { tripsApi } from '@\u002Fservices\u002FtripsApi'\n\nexport const store = configureStore({\n    reducer: {\n        [tripsApi.reducerPath]: tripsApi.reducer,\n    },\n    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(tripsApi.middleware),\n})\n\nsetupListeners(store.dispatch)\n\nexport type RootState = ReturnType\u003Ctypeof store.getState>\nexport type AppDispatch = typeof store.dispatch\n",[3829,31839,31840,31844,31858,31872,31886,31890,31904,31910,31923,31927,31957,31961,31965,31979,31983,32007],{"__ignoreMap":3827},[3832,31841,31842],{"class":3834,"line":3835},[3832,31843,9494],{"class":3838},[3832,31845,31846,31848,31850,31852,31854,31856],{"class":3834,"line":3842},[3832,31847,3846],{"class":3845},[3832,31849,3850],{"class":3849},[3832,31851,9503],{"class":3853},[3832,31853,3863],{"class":3849},[3832,31855,3866],{"class":3845},[3832,31857,3870],{"class":3869},[3832,31859,31860,31862,31864,31866,31868,31870],{"class":3834,"line":3873},[3832,31861,3846],{"class":3845},[3832,31863,3850],{"class":3849},[3832,31865,9518],{"class":3853},[3832,31867,3863],{"class":3849},[3832,31869,3866],{"class":3845},[3832,31871,9525],{"class":3869},[3832,31873,31874,31876,31878,31880,31882,31884],{"class":3834,"line":3880},[3832,31875,3846],{"class":3845},[3832,31877,3850],{"class":3849},[3832,31879,24368],{"class":3853},[3832,31881,3863],{"class":3849},[3832,31883,3866],{"class":3845},[3832,31885,6537],{"class":3869},[3832,31887,31888],{"class":3834,"line":3886},[3832,31889,3877],{"emptyLinePlaceholder":3876},[3832,31891,31892,31894,31896,31898,31900,31902],{"class":3834,"line":3900},[3832,31893,4105],{"class":3845},[3832,31895,4108],{"class":3889},[3832,31897,9554],{"class":4042},[3832,31899,4114],{"class":3849},[3832,31901,9503],{"class":4117},[3832,31903,4267],{"class":3849},[3832,31905,31906,31908],{"class":3834,"line":3912},[3832,31907,9565],{"class":3853},[3832,31909,3897],{"class":3849},[3832,31911,31912,31915,31917,31919,31921],{"class":3834,"line":3922},[3832,31913,31914],{"class":3853},"        [tripsApi.reducerPath]:",[3832,31916,6231],{"class":3853},[3832,31918,4183],{"class":3849},[3832,31920,9584],{"class":3853},[3832,31922,4072],{"class":3849},[3832,31924,31925],{"class":3834,"line":3932},[3832,31926,4560],{"class":3849},[3832,31928,31929,31931,31933,31935,31937,31939,31941,31943,31945,31947,31949,31951,31953,31955],{"class":3834,"line":3942},[3832,31930,9595],{"class":4117},[3832,31932,4304],{"class":3853},[3832,31934,4307],{"class":3849},[3832,31936,9602],{"class":3853},[3832,31938,4313],{"class":3849},[3832,31940,4140],{"class":3889},[3832,31942,29876],{"class":4117},[3832,31944,9620],{"class":3849},[3832,31946,9623],{"class":4117},[3832,31948,4162],{"class":3849},[3832,31950,24368],{"class":3853},[3832,31952,4183],{"class":3849},[3832,31954,9632],{"class":3853},[3832,31956,5165],{"class":3849},[3832,31958,31959],{"class":3834,"line":3948},[3832,31960,4566],{"class":3849},[3832,31962,31963],{"class":3834,"line":3953},[3832,31964,3877],{"emptyLinePlaceholder":3876},[3832,31966,31967,31969,31971,31973,31975,31977],{"class":3834,"line":3959},[3832,31968,9518],{"class":4117},[3832,31970,4162],{"class":3849},[3832,31972,9656],{"class":3853},[3832,31974,4183],{"class":3849},[3832,31976,4809],{"class":3853},[3832,31978,4168],{"class":3849},[3832,31980,31981],{"class":3834,"line":3969},[3832,31982,3877],{"emptyLinePlaceholder":3876},[3832,31984,31985,31987,31989,31991,31993,31995,31997,31999,32001,32003,32005],{"class":3834,"line":3986},[3832,31986,4105],{"class":3845},[3832,31988,9673],{"class":3889},[3832,31990,9676],{"class":3893},[3832,31992,4114],{"class":3849},[3832,31994,9681],{"class":3893},[3832,31996,5084],{"class":3849},[3832,31998,9686],{"class":3889},[3832,32000,9554],{"class":3853},[3832,32002,4183],{"class":3849},[3832,32004,9693],{"class":3853},[3832,32006,4898],{"class":3849},[3832,32008,32009,32011,32013,32015,32017,32019,32021,32023],{"class":3834,"line":4000},[3832,32010,4105],{"class":3845},[3832,32012,9673],{"class":3889},[3832,32014,9704],{"class":3893},[3832,32016,4114],{"class":3849},[3832,32018,9686],{"class":3889},[3832,32020,9554],{"class":3853},[3832,32022,4183],{"class":3849},[3832,32024,9715],{"class":3853},[3809,32026,32028,32029],{"id":32027},"_3-оновлення-головного-екрана-apptabstripsindextsx","3. Оновлення головного екрана ",[3829,32030,32031],{},"app\u002F(tabs)\u002Ftrips\u002Findex.tsx",[3822,32033,32035],{"className":4592,"code":32034,"language":4594,"meta":3827,"style":3827},"\u002F\u002F app\u002F(tabs)\u002Ftrips\u002Findex.tsx\nimport React from 'react'\nimport { View, FlatList, ActivityIndicator, RefreshControl, StyleSheet, Text } from 'react-native'\nimport { useRouter } from 'expo-router'\nimport { useGetTripsQuery } from '@\u002Fservices\u002FtripsApi'\nimport { TripCard } from '@\u002Ffeatures\u002Ftrips'\nimport { Screen, Button } from '@\u002Fshared\u002Fui'\n\nexport default function TripsScreen() {\n    const router = useRouter()\n    const { data: trips, isLoading, isFetching, isError, refetch } = useGetTripsQuery()\n\n    if (isLoading) {\n        return (\n            \u003CScreen style={styles.center}>\n                \u003CActivityIndicator size=\"large\" color=\"#2563eb\" \u002F>\n            \u003C\u002FScreen>\n        )\n    }\n\n    return (\n        \u003CScreen style={styles.container}>\n            \u003CView style={styles.header}>\n                \u003CText style={styles.title}>Мої Подорожі\u003C\u002FText>\n                \u003CButton title=\"+ Створити\" onPress={() => router.push('\u002Fcreate-trip')} \u002F>\n            \u003C\u002FView>\n\n            \u003CFlatList\n                data={trips}\n                keyExtractor={(item) => item.id}\n                renderItem={({ item }) => \u003CTripCard trip={item} onPress={() => router.push(`\u002Ftrips\u002F${item.id}`)} \u002F>}\n                refreshControl={\u003CRefreshControl refreshing={isFetching} onRefresh={refetch} tintColor=\"#2563eb\" \u002F>}\n                ListEmptyComponent={\n                    \u003CView style={styles.empty}>\n                        \u003CText style={styles.emptyText}>Список порожній. Створіть першу поїздку!\u003C\u002FText>\n                    \u003C\u002FView>\n                }\n            \u002F>\n        \u003C\u002FScreen>\n    )\n}\n\nconst styles = StyleSheet.create({\n    container: { flex: 1, padding: 16 },\n    center: { flex: 1, justifyContent: 'center', alignItems: 'center' },\n    header: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 },\n    title: { fontSize: 26, fontWeight: '800', color: '#0f172a' },\n    empty: { alignItems: 'center', marginTop: 40 },\n    emptyText: { color: '#64748b', fontSize: 15 },\n})\n",[3829,32036,32037,32042,32052,32086,32100,32114,32129,32149,32153,32166,32178,32212,32216,32226,32232,32254,32274,32282,32286,32290,32294,32300,32322,32344,32375,32415,32423,32427,32433,32445,32469,32539,32582,32591,32614,32646,32654,32658,32662,32670,32674,32678,32682,32698,32716,32740,32771,32796,32817,32837],{"__ignoreMap":3827},[3832,32038,32039],{"class":3834,"line":3835},[3832,32040,32041],{"class":3838},"\u002F\u002F app\u002F(tabs)\u002Ftrips\u002Findex.tsx\n",[3832,32043,32044,32046,32048,32050],{"class":3834,"line":3842},[3832,32045,3846],{"class":3845},[3832,32047,4608],{"class":3853},[3832,32049,5856],{"class":3845},[3832,32051,4621],{"class":3869},[3832,32053,32054,32056,32058,32060,32062,32064,32066,32068,32070,32072,32074,32076,32078,32080,32082,32084],{"class":3834,"line":3873},[3832,32055,3846],{"class":3845},[3832,32057,3850],{"class":3849},[3832,32059,4630],{"class":3853},[3832,32061,3857],{"class":3849},[3832,32063,4640],{"class":3853},[3832,32065,3857],{"class":3849},[3832,32067,4645],{"class":3853},[3832,32069,3857],{"class":3849},[3832,32071,18431],{"class":3853},[3832,32073,3857],{"class":3849},[3832,32075,9868],{"class":3853},[3832,32077,3857],{"class":3849},[3832,32079,4635],{"class":3853},[3832,32081,3863],{"class":3849},[3832,32083,3866],{"class":3845},[3832,32085,4652],{"class":3869},[3832,32087,32088,32090,32092,32094,32096,32098],{"class":3834,"line":3880},[3832,32089,3846],{"class":3845},[3832,32091,3850],{"class":3849},[3832,32093,20316],{"class":3853},[3832,32095,3863],{"class":3849},[3832,32097,3866],{"class":3845},[3832,32099,20323],{"class":3869},[3832,32101,32102,32104,32106,32108,32110,32112],{"class":3834,"line":3886},[3832,32103,3846],{"class":3845},[3832,32105,3850],{"class":3849},[3832,32107,6499],{"class":3853},[3832,32109,3863],{"class":3849},[3832,32111,3866],{"class":3845},[3832,32113,6537],{"class":3869},[3832,32115,32116,32118,32120,32122,32124,32126],{"class":3834,"line":3900},[3832,32117,3846],{"class":3845},[3832,32119,3850],{"class":3849},[3832,32121,17133],{"class":3853},[3832,32123,3863],{"class":3849},[3832,32125,3866],{"class":3845},[3832,32127,32128],{"class":3869}," '@\u002Ffeatures\u002Ftrips'\n",[3832,32130,32131,32133,32135,32138,32140,32142,32144,32146],{"class":3834,"line":3912},[3832,32132,3846],{"class":3845},[3832,32134,3850],{"class":3849},[3832,32136,32137],{"class":3853},"Screen",[3832,32139,3857],{"class":3849},[3832,32141,18725],{"class":3853},[3832,32143,3863],{"class":3849},[3832,32145,3866],{"class":3845},[3832,32147,32148],{"class":3869}," '@\u002Fshared\u002Fui'\n",[3832,32150,32151],{"class":3834,"line":3922},[3832,32152,3877],{"emptyLinePlaceholder":3876},[3832,32154,32155,32157,32159,32161,32164],{"class":3834,"line":3932},[3832,32156,4105],{"class":3845},[3832,32158,4579],{"class":3845},[3832,32160,4699],{"class":3889},[3832,32162,32163],{"class":4117}," TripsScreen",[3832,32165,4705],{"class":3849},[3832,32167,32168,32170,32172,32174,32176],{"class":3834,"line":3942},[3832,32169,4710],{"class":3889},[3832,32171,20345],{"class":4042},[3832,32173,4114],{"class":3849},[3832,32175,20316],{"class":4117},[3832,32177,4230],{"class":3849},[3832,32179,32180,32182,32184,32186,32188,32190,32192,32194,32196,32198,32200,32202,32204,32206,32208,32210],{"class":3834,"line":3948},[3832,32181,4710],{"class":3889},[3832,32183,3850],{"class":3849},[3832,32185,6565],{"class":3853},[3832,32187,3906],{"class":3849},[3832,32189,4458],{"class":4042},[3832,32191,3857],{"class":3849},[3832,32193,4371],{"class":4042},[3832,32195,3857],{"class":3849},[3832,32197,9744],{"class":4042},[3832,32199,3857],{"class":3849},[3832,32201,18517],{"class":4042},[3832,32203,3857],{"class":3849},[3832,32205,18336],{"class":4042},[3832,32207,4748],{"class":3849},[3832,32209,6499],{"class":4117},[3832,32211,4230],{"class":3849},[3832,32213,32214],{"class":3834,"line":3953},[3832,32215,3877],{"emptyLinePlaceholder":3876},[3832,32217,32218,32220,32222,32224],{"class":3834,"line":3959},[3832,32219,4821],{"class":3845},[3832,32221,4307],{"class":3849},[3832,32223,4371],{"class":3853},[3832,32225,4189],{"class":3849},[3832,32227,32228,32230],{"class":3834,"line":3969},[3832,32229,4220],{"class":3845},[3832,32231,4914],{"class":3849},[3832,32233,32234,32236,32238,32240,32242,32244,32246,32248,32250,32252],{"class":3834,"line":3986},[3832,32235,7532],{"class":4834},[3832,32237,32137],{"class":3893},[3832,32239,8467],{"class":4840},[3832,32241,4844],{"class":3849},[3832,32243,4885],{"class":3889},[3832,32245,9970],{"class":3853},[3832,32247,4183],{"class":4947},[3832,32249,9975],{"class":3853},[3832,32251,4890],{"class":3889},[3832,32253,4898],{"class":4834},[3832,32255,32256,32258,32260,32262,32264,32266,32268,32270,32272],{"class":3834,"line":4000},[3832,32257,9984],{"class":4834},[3832,32259,4645],{"class":3893},[3832,32261,4841],{"class":4840},[3832,32263,4844],{"class":3849},[3832,32265,4847],{"class":3869},[3832,32267,9995],{"class":4840},[3832,32269,4844],{"class":3849},[3832,32271,30256],{"class":3869},[3832,32273,4850],{"class":4834},[3832,32275,32276,32278,32280],{"class":3834,"line":4020},[3832,32277,10039],{"class":4834},[3832,32279,32137],{"class":3893},[3832,32281,4898],{"class":4834},[3832,32283,32284],{"class":3834,"line":4025},[3832,32285,10048],{"class":3849},[3832,32287,32288],{"class":3834,"line":4030},[3832,32289,4236],{"class":3849},[3832,32291,32292],{"class":3834,"line":4036},[3832,32293,3877],{"emptyLinePlaceholder":3876},[3832,32295,32296,32298],{"class":3834,"line":4054},[3832,32297,4911],{"class":3845},[3832,32299,4914],{"class":3849},[3832,32301,32302,32304,32306,32308,32310,32312,32314,32316,32318,32320],{"class":3834,"line":4063},[3832,32303,4919],{"class":4834},[3832,32305,32137],{"class":3893},[3832,32307,8467],{"class":4840},[3832,32309,4844],{"class":3849},[3832,32311,4885],{"class":3889},[3832,32313,9970],{"class":3853},[3832,32315,4183],{"class":4947},[3832,32317,18796],{"class":3853},[3832,32319,4890],{"class":3889},[3832,32321,4898],{"class":4834},[3832,32323,32324,32326,32328,32330,32332,32334,32336,32338,32340,32342],{"class":3834,"line":4075},[3832,32325,7532],{"class":4834},[3832,32327,4630],{"class":3893},[3832,32329,8467],{"class":4840},[3832,32331,4844],{"class":3849},[3832,32333,4885],{"class":3889},[3832,32335,9970],{"class":3853},[3832,32337,4183],{"class":4947},[3832,32339,30325],{"class":3853},[3832,32341,4890],{"class":3889},[3832,32343,4898],{"class":4834},[3832,32345,32346,32348,32350,32352,32354,32356,32358,32360,32362,32364,32366,32369,32371,32373],{"class":3834,"line":4086},[3832,32347,9984],{"class":4834},[3832,32349,4635],{"class":3893},[3832,32351,8467],{"class":4840},[3832,32353,4844],{"class":3849},[3832,32355,4885],{"class":3889},[3832,32357,9970],{"class":3853},[3832,32359,4183],{"class":4947},[3832,32361,4998],{"class":3853},[3832,32363,4890],{"class":3889},[3832,32365,4879],{"class":4834},[3832,32367,32368],{"class":3849},"Мої Подорожі",[3832,32370,4893],{"class":4834},[3832,32372,4635],{"class":3893},[3832,32374,4898],{"class":4834},[3832,32376,32377,32379,32381,32383,32385,32388,32390,32392,32394,32396,32398,32400,32402,32404,32406,32409,32411,32413],{"class":3834,"line":4091},[3832,32378,9984],{"class":4834},[3832,32380,18725],{"class":3893},[3832,32382,18728],{"class":4840},[3832,32384,4844],{"class":3849},[3832,32386,32387],{"class":3869},"\"+ Створити\"",[3832,32389,18736],{"class":4840},[3832,32391,4844],{"class":3849},[3832,32393,4885],{"class":3889},[3832,32395,11455],{"class":4947},[3832,32397,4140],{"class":3889},[3832,32399,20345],{"class":3853},[3832,32401,4183],{"class":4947},[3832,32403,5327],{"class":4117},[3832,32405,4162],{"class":4947},[3832,32407,32408],{"class":3869},"'\u002Fcreate-trip'",[3832,32410,9460],{"class":4947},[3832,32412,4890],{"class":3889},[3832,32414,4850],{"class":4834},[3832,32416,32417,32419,32421],{"class":3834,"line":4096},[3832,32418,10039],{"class":4834},[3832,32420,4630],{"class":3893},[3832,32422,4898],{"class":4834},[3832,32424,32425],{"class":3834,"line":4102},[3832,32426,3877],{"emptyLinePlaceholder":3876},[3832,32428,32429,32431],{"class":3834,"line":4123},[3832,32430,7532],{"class":4834},[3832,32432,4922],{"class":3893},[3832,32434,32435,32437,32439,32441,32443],{"class":3834,"line":4131},[3832,32436,17103],{"class":4840},[3832,32438,4844],{"class":3849},[3832,32440,4885],{"class":3889},[3832,32442,4458],{"class":3853},[3832,32444,3945],{"class":3889},[3832,32446,32447,32449,32451,32453,32455,32457,32459,32461,32463,32465,32467],{"class":3834,"line":4145},[3832,32448,18937],{"class":4840},[3832,32450,4844],{"class":3849},[3832,32452,4885],{"class":3889},[3832,32454,4162],{"class":4947},[3832,32456,4950],{"class":3853},[3832,32458,4313],{"class":4947},[3832,32460,4140],{"class":3889},[3832,32462,4957],{"class":3853},[3832,32464,4183],{"class":4947},[3832,32466,4962],{"class":3853},[3832,32468,3945],{"class":3889},[3832,32470,32471,32473,32475,32477,32479,32481,32483,32485,32487,32489,32491,32493,32495,32497,32499,32501,32503,32505,32507,32509,32511,32513,32515,32517,32519,32521,32523,32525,32527,32529,32531,32533,32535,32537],{"class":3834,"line":4171},[3832,32472,17116],{"class":4840},[3832,32474,4844],{"class":3849},[3832,32476,4885],{"class":3889},[3832,32478,4976],{"class":4947},[3832,32480,4950],{"class":3853},[3832,32482,4981],{"class":4947},[3832,32484,4140],{"class":3889},[3832,32486,4835],{"class":4834},[3832,32488,17133],{"class":3893},[3832,32490,17136],{"class":4840},[3832,32492,4844],{"class":3849},[3832,32494,4885],{"class":3889},[3832,32496,4950],{"class":3853},[3832,32498,4890],{"class":3889},[3832,32500,18736],{"class":4840},[3832,32502,4844],{"class":3849},[3832,32504,4885],{"class":3889},[3832,32506,11455],{"class":4947},[3832,32508,4140],{"class":3889},[3832,32510,20345],{"class":3853},[3832,32512,4183],{"class":4947},[3832,32514,5327],{"class":4117},[3832,32516,4162],{"class":4947},[3832,32518,23663],{"class":3869},[3832,32520,11249],{"class":3889},[3832,32522,4950],{"class":3853},[3832,32524,4183],{"class":4947},[3832,32526,4962],{"class":3853},[3832,32528,4890],{"class":3889},[3832,32530,11514],{"class":3869},[3832,32532,9460],{"class":4947},[3832,32534,4890],{"class":3889},[3832,32536,17147],{"class":4834},[3832,32538,3945],{"class":3889},[3832,32540,32541,32543,32545,32547,32549,32551,32553,32555,32557,32559,32561,32563,32565,32567,32569,32571,32574,32576,32578,32580],{"class":3834,"line":4192},[3832,32542,19010],{"class":4840},[3832,32544,4844],{"class":3849},[3832,32546,4885],{"class":3889},[3832,32548,5084],{"class":4834},[3832,32550,18431],{"class":3893},[3832,32552,30554],{"class":4840},[3832,32554,4844],{"class":3849},[3832,32556,4885],{"class":3889},[3832,32558,9744],{"class":3853},[3832,32560,4890],{"class":3889},[3832,32562,30565],{"class":4840},[3832,32564,4844],{"class":3849},[3832,32566,4885],{"class":3889},[3832,32568,18336],{"class":3853},[3832,32570,4890],{"class":3889},[3832,32572,32573],{"class":4840}," tintColor",[3832,32575,4844],{"class":3849},[3832,32577,30256],{"class":3869},[3832,32579,17147],{"class":4834},[3832,32581,3945],{"class":3889},[3832,32583,32584,32587,32589],{"class":3834,"line":4211},[3832,32585,32586],{"class":4840},"                ListEmptyComponent",[3832,32588,4844],{"class":3849},[3832,32590,11782],{"class":3889},[3832,32592,32593,32595,32597,32599,32601,32603,32605,32607,32610,32612],{"class":3834,"line":4217},[3832,32594,10274],{"class":4834},[3832,32596,4630],{"class":3893},[3832,32598,8467],{"class":4840},[3832,32600,4844],{"class":3849},[3832,32602,4885],{"class":3889},[3832,32604,9970],{"class":3853},[3832,32606,4183],{"class":4947},[3832,32608,32609],{"class":3853},"empty",[3832,32611,4890],{"class":3889},[3832,32613,4898],{"class":4834},[3832,32615,32616,32618,32620,32622,32624,32626,32628,32630,32633,32635,32637,32640,32642,32644],{"class":3834,"line":4233},[3832,32617,30623],{"class":4834},[3832,32619,4635],{"class":3893},[3832,32621,8467],{"class":4840},[3832,32623,4844],{"class":3849},[3832,32625,4885],{"class":3889},[3832,32627,9970],{"class":3853},[3832,32629,4183],{"class":4947},[3832,32631,32632],{"class":3853},"emptyText",[3832,32634,4890],{"class":3889},[3832,32636,4879],{"class":4834},[3832,32638,32639],{"class":4947},"Список порожній. Створіть першу поїздку!",[3832,32641,4893],{"class":4834},[3832,32643,4635],{"class":3893},[3832,32645,4898],{"class":4834},[3832,32647,32648,32650,32652],{"class":3834,"line":4239},[3832,32649,30745],{"class":4834},[3832,32651,4630],{"class":3893},[3832,32653,4898],{"class":4834},[3832,32655,32656],{"class":3834,"line":4244},[3832,32657,15165],{"class":3889},[3832,32659,32660],{"class":3834,"line":4249},[3832,32661,7581],{"class":4834},[3832,32663,32664,32666,32668],{"class":3834,"line":4255},[3832,32665,7596],{"class":4834},[3832,32667,32137],{"class":3893},[3832,32669,4898],{"class":4834},[3832,32671,32672],{"class":3834,"line":4270},[3832,32673,5018],{"class":3849},[3832,32675,32676],{"class":3834,"line":4281},[3832,32677,3945],{"class":3849},[3832,32679,32680],{"class":3834,"line":4289},[3832,32681,3877],{"emptyLinePlaceholder":3876},[3832,32683,32684,32686,32688,32690,32692,32694,32696],{"class":3834,"line":4298},[3832,32685,4039],{"class":3889},[3832,32687,10385],{"class":4042},[3832,32689,4114],{"class":3849},[3832,32691,9868],{"class":3853},[3832,32693,4183],{"class":3849},[3832,32695,10394],{"class":4117},[3832,32697,4267],{"class":3849},[3832,32699,32700,32702,32704,32706,32708,32710,32712,32714],{"class":3834,"line":4320},[3832,32701,30801],{"class":3853},[3832,32703,3850],{"class":3849},[3832,32705,30636],{"class":3853},[3832,32707,10411],{"class":5726},[3832,32709,3857],{"class":3849},[3832,32711,20632],{"class":3853},[3832,32713,10500],{"class":5726},[3832,32715,5145],{"class":3849},[3832,32717,32718,32720,32722,32724,32726,32728,32730,32732,32734,32736,32738],{"class":3834,"line":4326},[3832,32719,10401],{"class":3853},[3832,32721,3850],{"class":3849},[3832,32723,30636],{"class":3853},[3832,32725,10411],{"class":5726},[3832,32727,3857],{"class":3849},[3832,32729,30837],{"class":3853},[3832,32731,10421],{"class":3869},[3832,32733,3857],{"class":3849},[3832,32735,30844],{"class":3853},[3832,32737,10421],{"class":3869},[3832,32739,5145],{"class":3849},[3832,32741,32742,32744,32746,32748,32750,32752,32754,32757,32759,32761,32763,32765,32767,32769],{"class":3834,"line":4332},[3832,32743,30853],{"class":3853},[3832,32745,3850],{"class":3849},[3832,32747,30895],{"class":3853},[3832,32749,30898],{"class":3869},[3832,32751,3857],{"class":3849},[3832,32753,30837],{"class":3853},[3832,32755,32756],{"class":3869}," 'space-between'",[3832,32758,3857],{"class":3849},[3832,32760,30844],{"class":3853},[3832,32762,10421],{"class":3869},[3832,32764,3857],{"class":3849},[3832,32766,30874],{"class":3853},[3832,32768,10500],{"class":5726},[3832,32770,5145],{"class":3849},[3832,32772,32773,32775,32777,32779,32782,32784,32786,32788,32790,32792,32794],{"class":3834,"line":4363},[3832,32774,10658],{"class":3853},[3832,32776,3850],{"class":3849},[3832,32778,30858],{"class":3853},[3832,32780,32781],{"class":5726}," 26",[3832,32783,3857],{"class":3849},[3832,32785,30866],{"class":3853},[3832,32787,30869],{"class":3869},[3832,32789,3857],{"class":3849},[3832,32791,30881],{"class":3853},[3832,32793,10688],{"class":3869},[3832,32795,5145],{"class":3849},[3832,32797,32798,32801,32803,32805,32807,32809,32812,32815],{"class":3834,"line":4379},[3832,32799,32800],{"class":3853},"    empty:",[3832,32802,3850],{"class":3849},[3832,32804,30844],{"class":3853},[3832,32806,10421],{"class":3869},[3832,32808,3857],{"class":3849},[3832,32810,32811],{"class":3853},"marginTop:",[3832,32813,32814],{"class":5726}," 40",[3832,32816,5145],{"class":3849},[3832,32818,32819,32822,32824,32826,32828,32830,32832,32835],{"class":3834,"line":4394},[3832,32820,32821],{"class":3853},"    emptyText:",[3832,32823,3850],{"class":3849},[3832,32825,30881],{"class":3853},[3832,32827,10480],{"class":3869},[3832,32829,3857],{"class":3849},[3832,32831,30858],{"class":3853},[3832,32833,32834],{"class":5726}," 15",[3832,32836,5145],{"class":3849},[3832,32838,32839],{"class":3834,"line":4400},[3832,32840,4566],{"class":3849},[3793,32842],{},[3796,32844,32846],{"id":32845},"резюме-розділу","Резюме розділу",[3738,32848,32849,32858,32868,32877],{},[3741,32850,32852,32854,32855,32857],{"icon":1946,"title":32851},"🚀 Декларативний API",[3829,32853,6153],{}," повністю замінює ручні слайси, редюсери та ",[3829,32856,3860],{}," для роботи з мережею, автоматично генеруючи типізовані хуки.",[3741,32859,32861,32862,18007,32864,32867],{"icon":12033,"title":32860},"🏷️ Гранулярні Теги","Комбінація тегів ",[3829,32863,26231],{},[3829,32865,32866],{},"{ type: 'Trip', id }"," забезпечує точкову інвалідацію лише змінених сутностей без зайвих мережевих запитів.",[3741,32869,32870,3857,32872,18007,32874,32876],{"icon":6771,"title":6772},[3829,32871,6776],{},[3829,32873,6780],{},[3829,32875,12217],{}," забезпечують актуальність даних при поверненні з фону та раціональне використання оперативної пам'яті.",[3741,32878,32880,32881,32883,32884,32887],{"icon":92,"title":32879},"⚡ Optimistic UI","Механізм ",[3829,32882,27851],{}," дозволяє змінювати локальний інтерфейс за 0 мс із надійним автоматичним відкатом (",[3829,32885,32886],{},"rollback",") при помилці бекенду.",[3793,32889],{},[3796,32891,32893],{"id":32892},"практичні-завдання","Практичні завдання",[8608,32895,32896,32909],{},[8611,32897,32898],{},[8614,32899,32900,32903,32906],{},[8617,32901,32902],{"align":8619},"Рівень складності",[8617,32904,32905],{"align":8619},"Назва завдання",[8617,32907,32908],{"align":8619},"Формулювання вимог",[8641,32910,32911,32935,32952],{},[8614,32912,32913,32918,32921],{},[8646,32914,32915],{"align":8619},[3770,32916,32917],{},"Базовий (Basic)",[8646,32919,32920],{"align":8619},"Додавання статусу поїздки",[8646,32922,32923,32924,32927,32928,18007,32931,32934],{"align":8619},"Додати mutation ",[3829,32925,32926],{},"toggleTripStatus(id)"," (перемикання між ",[3829,32929,32930],{},"planned",[3829,32932,32933],{},"completed","). Налаштувати теги так, щоб список автоматично відображав новий статус.",[8614,32936,32937,32942,32945],{},[8646,32938,32939],{"align":8619},[3770,32940,32941],{},"Середній (Intermediate)",[8646,32943,32944],{"align":8619},"Пошук із затримкою (Debounce)",[8646,32946,32947,32948,32951],{"align":8619},"Створити поле пошуку в заголовку списку. Використати хук ",[3829,32949,32950],{},"useGetFilteredTripsQuery({ search })"," разом із кастомним хуком дебаунсу (300 мс), щоб не спамити бекенд при кожному натисканні клавіші.",[8614,32953,32954,32959,32962],{},[8646,32955,32956],{"align":8619},[3770,32957,32958],{},"Просунутий (Advanced)",[8646,32960,32961],{"align":8619},"Оптимістичне видалення з Rollback",[8646,32963,32964,32965,32967,32968,32970],{"align":8619},"Реалізувати ",[3829,32966,22455],{}," через ",[3829,32969,27851],{}," з миттєвим видаленням картки зі списку та демонстрацією Snackbar-повідомлення з кнопкою «Скасувати».",[3793,32972],{},[3796,32974,32976],{"id":32975},"поширені-запитання-faq","Поширені запитання (FAQ)",[8777,32978,32979,32987,33006],{},[8780,32980,32983,32984,32986],{"icon":32981,"title":32982},"i-lucide-alert-circle","Чому не можна зберігати всі серверні дані в звичайному createSlice?","Звичайний ",[3829,32985,3854],{}," не знає про життєвий цикл мережевих підписок, не вміє автоматично дедуплікувати паралельні виклики з різних компонентів, не має вбудованого таймера очищення пам'яті (Garbage Collection) та вимагає написання сотень рядків коду для синхронізації після кожної мутації.",[8780,32988,32990,32993,32994,32997,32998,33001,33002,33005],{"icon":8782,"title":32989},"Чим відрізняється isLoading від isFetching?",[3829,32991,32992],{},"isLoading: true"," лише під час ",[3770,32995,32996],{},"найпершого запиту",", коли в кеші взагалі немає даних (ідеально для показу великого Skeleton). ",[3829,32999,33000],{},"isFetching: true"," під час ",[3770,33003,33004],{},"будь-якого мережевого запиту",", навіть якщо старі дані вже відмальовані на екрані (ідеально для маленького спінера оновлення).",[8780,33007,33010,33011,33013,33014,33016,33017,33020],{"icon":33008,"title":33009},"i-lucide-shield-alert","Як обробити 401 Unauthorized та оновити Refresh Token у RTK Query?","Для цього створюється кастомна функція-обгортка ",[3829,33012,14154],{}," над ",[3829,33015,6158],{}," з використанням ",[3829,33018,33019],{},"async-mutex",". Якщо запит повертає статус 401, функція блокує паралельні запити, оновлює токен, записує його в store і повторює початковий виклик.",[3793,33022],{},[3796,33024,33026],{"id":33025},"просунуті-техніки-rtk-query","Просунуті техніки RTK Query",[3801,33028,33029],{},"Тепер, коли ви опанували основи Query, Mutations та систему тегів, розглянемо просунуті техніки, які роблять UX вашого застосунку по-справжньому чудовим.",[3809,33031,33033],{"id":33032},"оптимістичні-оновлення-optimistic-updates","Оптимістичні оновлення (Optimistic Updates)",[3801,33035,33036,33038],{},[3770,33037,5420],{}," Коли користувач натискає \"❤️ Додати в улюблене\", він чекає відповіді сервера 200-500мс перед тим як побачить зміну. Це відчувається повільно.",[3801,33040,33041,33043,33044,33047],{},[3770,33042,19624],{}," Змінюємо UI ",[3770,33045,33046],{},"миттєво"," (0мс), а якщо сервер поверне помилку — відкочуємо зміни назад.",[6852,33049,33051],{"id":33050},"приклад-лайк-поїздки","Приклад: Лайк поїздки",[3822,33053,33055],{"className":3824,"code":33054,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fservices\u002FtripsApi.ts\nexport const tripsApi = createApi({\n    endpoints: (builder) => ({\n        getTrips: builder.query\u003CTrip[], void>({\n            query: () => '\u002Ftrips',\n            providesTags: ['Trip'],\n        }),\n        \n        toggleFavorite: builder.mutation\u003Cvoid, string>({\n            query: (tripId) => ({\n                url: `\u002Ftrips\u002F${tripId}\u002Ffavorite`,\n                method: 'POST',\n            }),\n            \n            \u002F\u002F Lifecycle хук для оптимістичних оновлень\n            async onQueryStarted(tripId, { dispatch, queryFulfilled }) {\n                \u002F\u002F 1️⃣ ОПТИМІСТИЧНЕ ОНОВЛЕННЯ: Одразу змінюємо UI\n                const patchResult = dispatch(\n                    tripsApi.util.updateQueryData('getTrips', undefined, (draft) => {\n                        \u002F\u002F draft — це ImmerProxy, можна мутувати безпечно\n                        const trip = draft.find((t) => t.id === tripId)\n                        if (trip) {\n                            trip.isFavorite = !trip.isFavorite\n                        }\n                    })\n                )\n                \n                try {\n                    \u002F\u002F 2️⃣ Чекаємо відповіді сервера\n                    await queryFulfilled\n                    \u002F\u002F ✅ Успіх — UI вже оновлений, нічого не робимо\n                } catch {\n                    \u002F\u002F 3️⃣ ROLLBACK: Помилка — відкочуємо зміни\n                    patchResult.undo()\n                    \n                    \u002F\u002F Показуємо повідомлення користувачу\n                    Toast.show({\n                        type: 'error',\n                        text1: 'Не вдалося оновити',\n                    })\n                }\n            },\n        }),\n    }),\n})\n\nexport const { useGetTripsQuery, useToggleFavoriteMutation } = tripsApi\n",[3829,33056,33057,33061,33075,33091,33111,33125,33135,33139,33143,33164,33180,33196,33204,33208,33212,33217,33237,33242,33254,33285,33290,33324,33334,33350,33354,33359,33363,33367,33373,33378,33384,33389,33397,33402,33412,33416,33421,33432,33441,33451,33455,33459,33463,33467,33471,33475,33479],{"__ignoreMap":3827},[3832,33058,33059],{"class":3834,"line":3835},[3832,33060,11022],{"class":3838},[3832,33062,33063,33065,33067,33069,33071,33073],{"class":3834,"line":3842},[3832,33064,4105],{"class":3845},[3832,33066,4108],{"class":3889},[3832,33068,6231],{"class":4042},[3832,33070,4114],{"class":3849},[3832,33072,6153],{"class":4117},[3832,33074,4267],{"class":3849},[3832,33076,33077,33079,33081,33083,33085,33087,33089],{"class":3834,"line":3873},[3832,33078,6288],{"class":4117},[3832,33080,4304],{"class":3853},[3832,33082,4307],{"class":3849},[3832,33084,4310],{"class":3853},[3832,33086,4313],{"class":3849},[3832,33088,4140],{"class":3889},[3832,33090,6301],{"class":3849},[3832,33092,33093,33095,33097,33099,33101,33103,33105,33107,33109],{"class":3834,"line":3880},[3832,33094,6311],{"class":3853},[3832,33096,6314],{"class":3853},[3832,33098,4183],{"class":3849},[3832,33100,6319],{"class":4117},[3832,33102,5084],{"class":3849},[3832,33104,3977],{"class":3893},[3832,33106,6326],{"class":3849},[3832,33108,6329],{"class":3893},[3832,33110,6332],{"class":3849},[3832,33112,33113,33115,33117,33119,33121,33123],{"class":3834,"line":3886},[3832,33114,6337],{"class":4117},[3832,33116,4304],{"class":3853},[3832,33118,4137],{"class":3849},[3832,33120,4140],{"class":3889},[3832,33122,6346],{"class":3869},[3832,33124,4072],{"class":3849},[3832,33126,33127,33129,33131,33133],{"class":3834,"line":3900},[3832,33128,6353],{"class":3853},[3832,33130,6274],{"class":3849},[3832,33132,6277],{"class":3869},[3832,33134,11605],{"class":3849},[3832,33136,33137],{"class":3834,"line":3912},[3832,33138,6367],{"class":3849},[3832,33140,33141],{"class":3834,"line":3922},[3832,33142,11390],{"class":3849},[3832,33144,33145,33148,33150,33152,33154,33156,33158,33160,33162],{"class":3834,"line":3932},[3832,33146,33147],{"class":3853},"        toggleFavorite:",[3832,33149,6314],{"class":3853},[3832,33151,4183],{"class":3849},[3832,33153,6384],{"class":4117},[3832,33155,5084],{"class":3849},[3832,33157,6329],{"class":3893},[3832,33159,3857],{"class":3849},[3832,33161,4008],{"class":3893},[3832,33163,6332],{"class":3849},[3832,33165,33166,33168,33170,33172,33174,33176,33178],{"class":3834,"line":3942},[3832,33167,6337],{"class":4117},[3832,33169,4304],{"class":3853},[3832,33171,4307],{"class":3849},[3832,33173,8350],{"class":3853},[3832,33175,4313],{"class":3849},[3832,33177,4140],{"class":3889},[3832,33179,6301],{"class":3849},[3832,33181,33182,33184,33186,33188,33190,33192,33194],{"class":3834,"line":3948},[3832,33183,6424],{"class":3853},[3832,33185,21826],{"class":3869},[3832,33187,11249],{"class":3889},[3832,33189,8350],{"class":3853},[3832,33191,4890],{"class":3889},[3832,33193,28010],{"class":3869},[3832,33195,4072],{"class":3849},[3832,33197,33198,33200,33202],{"class":3834,"line":3953},[3832,33199,6433],{"class":3853},[3832,33201,5125],{"class":3869},[3832,33203,4072],{"class":3849},[3832,33205,33206],{"class":3834,"line":3959},[3832,33207,6452],{"class":3849},[3832,33209,33210],{"class":3834,"line":3969},[3832,33211,8518],{"class":3849},[3832,33213,33214],{"class":3834,"line":3986},[3832,33215,33216],{"class":3838},"            \u002F\u002F Lifecycle хук для оптимістичних оновлень\n",[3832,33218,33219,33221,33223,33225,33227,33229,33231,33233,33235],{"class":3834,"line":4000},[3832,33220,28038],{"class":3889},[3832,33222,28041],{"class":4117},[3832,33224,4162],{"class":3849},[3832,33226,8350],{"class":3853},[3832,33228,4611],{"class":3849},[3832,33230,4809],{"class":3853},[3832,33232,3857],{"class":3849},[3832,33234,28054],{"class":3853},[3832,33236,8353],{"class":3849},[3832,33238,33239],{"class":3834,"line":4020},[3832,33240,33241],{"class":3838},"                \u002F\u002F 1️⃣ ОПТИМІСТИЧНЕ ОНОВЛЕННЯ: Одразу змінюємо UI\n",[3832,33243,33244,33246,33248,33250,33252],{"class":3834,"line":4025},[3832,33245,14926],{"class":3889},[3832,33247,28068],{"class":4042},[3832,33249,4114],{"class":3849},[3832,33251,4809],{"class":4117},[3832,33253,4120],{"class":3849},[3832,33255,33256,33259,33261,33263,33265,33267,33269,33271,33273,33275,33277,33279,33281,33283],{"class":3834,"line":4030},[3832,33257,33258],{"class":3853},"                    tripsApi",[3832,33260,4183],{"class":3849},[3832,33262,24373],{"class":3853},[3832,33264,4183],{"class":3849},[3832,33266,27857],{"class":4117},[3832,33268,4162],{"class":3849},[3832,33270,24383],{"class":3869},[3832,33272,3857],{"class":3849},[3832,33274,16886],{"class":3889},[3832,33276,4351],{"class":3849},[3832,33278,28105],{"class":3853},[3832,33280,4313],{"class":3849},[3832,33282,4140],{"class":3889},[3832,33284,3897],{"class":3849},[3832,33286,33287],{"class":3834,"line":4036},[3832,33288,33289],{"class":3838},"                        \u002F\u002F draft — це ImmerProxy, можна мутувати безпечно\n",[3832,33291,33292,33294,33296,33298,33300,33302,33304,33306,33308,33310,33312,33314,33316,33318,33320,33322],{"class":3834,"line":4054},[3832,33293,28120],{"class":3889},[3832,33295,17136],{"class":4042},[3832,33297,4114],{"class":3849},[3832,33299,28105],{"class":3853},[3832,33301,4183],{"class":3849},[3832,33303,19565],{"class":4117},[3832,33305,4753],{"class":3849},[3832,33307,19570],{"class":3853},[3832,33309,4313],{"class":3849},[3832,33311,4140],{"class":3889},[3832,33313,19575],{"class":3853},[3832,33315,4183],{"class":3849},[3832,33317,4962],{"class":3853},[3832,33319,5921],{"class":3849},[3832,33321,8350],{"class":3853},[3832,33323,4168],{"class":3849},[3832,33325,33326,33328,33330,33332],{"class":3834,"line":4063},[3832,33327,28155],{"class":3845},[3832,33329,4307],{"class":3849},[3832,33331,8412],{"class":3853},[3832,33333,4189],{"class":3849},[3832,33335,33336,33338,33340,33342,33344,33346,33348],{"class":3834,"line":4075},[3832,33337,28171],{"class":3853},[3832,33339,4183],{"class":3849},[3832,33341,27964],{"class":3853},[3832,33343,28178],{"class":3849},[3832,33345,8412],{"class":3853},[3832,33347,4183],{"class":3849},[3832,33349,28185],{"class":3853},[3832,33351,33352],{"class":3834,"line":4086},[3832,33353,9050],{"class":3849},[3832,33355,33356],{"class":3834,"line":4091},[3832,33357,33358],{"class":3849},"                    })\n",[3832,33360,33361],{"class":3834,"line":4096},[3832,33362,15026],{"class":3849},[3832,33364,33365],{"class":3834,"line":4102},[3832,33366,14921],{"class":3849},[3832,33368,33369,33371],{"class":3834,"line":4123},[3832,33370,28207],{"class":3845},[3832,33372,3897],{"class":3849},[3832,33374,33375],{"class":3834,"line":4131},[3832,33376,33377],{"class":3838},"                    \u002F\u002F 2️⃣ Чекаємо відповіді сервера\n",[3832,33379,33380,33382],{"class":3834,"line":4145},[3832,33381,28219],{"class":3845},[3832,33383,28222],{"class":3853},[3832,33385,33386],{"class":3834,"line":4171},[3832,33387,33388],{"class":3838},"                    \u002F\u002F ✅ Успіх — UI вже оновлений, нічого не робимо\n",[3832,33390,33391,33393,33395],{"class":3834,"line":4192},[3832,33392,15127],{"class":3849},[3832,33394,20571],{"class":3845},[3832,33396,3897],{"class":3849},[3832,33398,33399],{"class":3834,"line":4211},[3832,33400,33401],{"class":3838},"                    \u002F\u002F 3️⃣ ROLLBACK: Помилка — відкочуємо зміни\n",[3832,33403,33404,33406,33408,33410],{"class":3834,"line":4217},[3832,33405,28240],{"class":3853},[3832,33407,4183],{"class":3849},[3832,33409,28245],{"class":4117},[3832,33411,4230],{"class":3849},[3832,33413,33414],{"class":3834,"line":4233},[3832,33415,15092],{"class":3849},[3832,33417,33418],{"class":3834,"line":4239},[3832,33419,33420],{"class":3838},"                    \u002F\u002F Показуємо повідомлення користувачу\n",[3832,33422,33423,33426,33428,33430],{"class":3834,"line":4244},[3832,33424,33425],{"class":3853},"                    Toast",[3832,33427,4183],{"class":3849},[3832,33429,21340],{"class":4117},[3832,33431,4267],{"class":3849},[3832,33433,33434,33437,33439],{"class":3834,"line":4249},[3832,33435,33436],{"class":3853},"                        type:",[3832,33438,22120],{"class":3869},[3832,33440,4072],{"class":3849},[3832,33442,33443,33446,33449],{"class":3834,"line":4255},[3832,33444,33445],{"class":3853},"                        text1:",[3832,33447,33448],{"class":3869}," 'Не вдалося оновити'",[3832,33450,4072],{"class":3849},[3832,33452,33453],{"class":3834,"line":4270},[3832,33454,33358],{"class":3849},[3832,33456,33457],{"class":3834,"line":4281},[3832,33458,15165],{"class":3849},[3832,33460,33461],{"class":3834,"line":4289},[3832,33462,13923],{"class":3849},[3832,33464,33465],{"class":3834,"line":4298},[3832,33466,6367],{"class":3849},[3832,33468,33469],{"class":3834,"line":4320},[3832,33470,6475],{"class":3849},[3832,33472,33473],{"class":3834,"line":4326},[3832,33474,4566],{"class":3849},[3832,33476,33477],{"class":3834,"line":4332},[3832,33478,3877],{"emptyLinePlaceholder":3876},[3832,33480,33481,33483,33485,33487,33489,33491,33494,33496],{"class":3834,"line":4363},[3832,33482,4105],{"class":3845},[3832,33484,4108],{"class":3889},[3832,33486,3850],{"class":3849},[3832,33488,6499],{"class":4042},[3832,33490,3857],{"class":3849},[3832,33492,33493],{"class":4042},"useToggleFavoriteMutation",[3832,33495,4748],{"class":3849},[3832,33497,6509],{"class":3853},[3801,33499,33500],{},[3770,33501,15715],{},[3822,33503,33505],{"className":4592,"code":33504,"language":4594,"meta":3827,"style":3827},"function TripCard({ trip }) {\n    const [toggleFavorite, { isLoading }] = useToggleFavoriteMutation()\n    \n    const handleFavoritePress = () => {\n        toggleFavorite(trip.id)\n        \u002F\u002F UI оновиться МИТТЄВО ⚡\n        \u002F\u002F Користувач не чекає відповіді сервера\n    }\n    \n    return (\n        \u003CView style={styles.card}>\n            \u003CText>{trip.title}\u003C\u002FText>\n            \u003CTouchableOpacity onPress={handleFavoritePress}>\n                \u003CText style={styles.icon}>\n                    {trip.isFavorite ? '❤️' : '🤍'}\n                \u003C\u002FText>\n            \u003C\u002FTouchableOpacity>\n        \u003C\u002FView>\n    )\n}\n",[3829,33506,33507,33519,33538,33542,33555,33570,33575,33580,33584,33588,33594,33616,33640,33660,33683,33706,33714,33722,33730,33734],{"__ignoreMap":3827},[3832,33508,33509,33511,33513,33515,33517],{"class":3834,"line":3835},[3832,33510,7416],{"class":3889},[3832,33512,22440],{"class":4117},[3832,33514,4976],{"class":3849},[3832,33516,8412],{"class":3853},[3832,33518,8353],{"class":3849},[3832,33520,33521,33523,33525,33528,33530,33532,33534,33536],{"class":3834,"line":3842},[3832,33522,4710],{"class":3889},[3832,33524,6274],{"class":3849},[3832,33526,33527],{"class":4042},"toggleFavorite",[3832,33529,4611],{"class":3849},[3832,33531,4371],{"class":4042},[3832,33533,19279],{"class":3849},[3832,33535,33493],{"class":4117},[3832,33537,4230],{"class":3849},[3832,33539,33540],{"class":3834,"line":3873},[3832,33541,4724],{"class":3849},[3832,33543,33544,33546,33549,33551,33553],{"class":3834,"line":3880},[3832,33545,4710],{"class":3889},[3832,33547,33548],{"class":4117}," handleFavoritePress",[3832,33550,19297],{"class":3849},[3832,33552,4140],{"class":3889},[3832,33554,3897],{"class":3849},[3832,33556,33557,33560,33562,33564,33566,33568],{"class":3834,"line":3886},[3832,33558,33559],{"class":4117},"        toggleFavorite",[3832,33561,4162],{"class":3849},[3832,33563,8412],{"class":3853},[3832,33565,4183],{"class":3849},[3832,33567,4962],{"class":3853},[3832,33569,4168],{"class":3849},[3832,33571,33572],{"class":3834,"line":3900},[3832,33573,33574],{"class":3838},"        \u002F\u002F UI оновиться МИТТЄВО ⚡\n",[3832,33576,33577],{"class":3834,"line":3912},[3832,33578,33579],{"class":3838},"        \u002F\u002F Користувач не чекає відповіді сервера\n",[3832,33581,33582],{"class":3834,"line":3922},[3832,33583,4236],{"class":3849},[3832,33585,33586],{"class":3834,"line":3932},[3832,33587,4724],{"class":3849},[3832,33589,33590,33592],{"class":3834,"line":3942},[3832,33591,4911],{"class":3845},[3832,33593,4914],{"class":3849},[3832,33595,33596,33598,33600,33602,33604,33606,33608,33610,33612,33614],{"class":3834,"line":3948},[3832,33597,4919],{"class":4834},[3832,33599,4630],{"class":3893},[3832,33601,8467],{"class":4840},[3832,33603,4844],{"class":3849},[3832,33605,4885],{"class":3889},[3832,33607,9970],{"class":3853},[3832,33609,4183],{"class":4947},[3832,33611,3741],{"class":3853},[3832,33613,4890],{"class":3889},[3832,33615,4898],{"class":4834},[3832,33617,33618,33620,33622,33624,33626,33628,33630,33632,33634,33636,33638],{"class":3834,"line":3953},[3832,33619,7532],{"class":4834},[3832,33621,4635],{"class":3893},[3832,33623,4879],{"class":4834},[3832,33625,4885],{"class":3889},[3832,33627,8412],{"class":3853},[3832,33629,4183],{"class":4947},[3832,33631,4998],{"class":3853},[3832,33633,4890],{"class":3889},[3832,33635,4893],{"class":4834},[3832,33637,4635],{"class":3893},[3832,33639,4898],{"class":4834},[3832,33641,33642,33644,33647,33649,33651,33653,33656,33658],{"class":3834,"line":3959},[3832,33643,7532],{"class":4834},[3832,33645,33646],{"class":3893},"TouchableOpacity",[3832,33648,18736],{"class":4840},[3832,33650,4844],{"class":3849},[3832,33652,4885],{"class":3889},[3832,33654,33655],{"class":3853},"handleFavoritePress",[3832,33657,4890],{"class":3889},[3832,33659,4898],{"class":4834},[3832,33661,33662,33664,33666,33668,33670,33672,33674,33676,33679,33681],{"class":3834,"line":3969},[3832,33663,9984],{"class":4834},[3832,33665,4635],{"class":3893},[3832,33667,8467],{"class":4840},[3832,33669,4844],{"class":3849},[3832,33671,4885],{"class":3889},[3832,33673,9970],{"class":3853},[3832,33675,4183],{"class":4947},[3832,33677,33678],{"class":3853},"icon",[3832,33680,4890],{"class":3889},[3832,33682,4898],{"class":4834},[3832,33684,33685,33688,33690,33692,33694,33696,33699,33701,33704],{"class":3834,"line":3986},[3832,33686,33687],{"class":3889},"                    {",[3832,33689,8412],{"class":3853},[3832,33691,4183],{"class":4947},[3832,33693,27964],{"class":3853},[3832,33695,8488],{"class":3849},[3832,33697,33698],{"class":3869}," '❤️'",[3832,33700,8494],{"class":3849},[3832,33702,33703],{"class":3869}," '🤍'",[3832,33705,3945],{"class":3889},[3832,33707,33708,33710,33712],{"class":3834,"line":4000},[3832,33709,10146],{"class":4834},[3832,33711,4635],{"class":3893},[3832,33713,4898],{"class":4834},[3832,33715,33716,33718,33720],{"class":3834,"line":4020},[3832,33717,10039],{"class":4834},[3832,33719,33646],{"class":3893},[3832,33721,4898],{"class":4834},[3832,33723,33724,33726,33728],{"class":3834,"line":4025},[3832,33725,7596],{"class":4834},[3832,33727,4630],{"class":3893},[3832,33729,4898],{"class":4834},[3832,33731,33732],{"class":3834,"line":4030},[3832,33733,5018],{"class":3849},[3832,33735,33736],{"class":3834,"line":4036},[3832,33737,3945],{"class":3849},[3801,33739,33740],{},[3770,33741,33742],{},"Що відбувається покроково:",[5430,33744,33745,33749,33752,33756,33759,33763],{},[3809,33746,33748],{"id":33747},"користувач-натискає-️","Користувач натискає ❤️",[3801,33750,33751],{},"Іконка МИТТЄВО змінюється з 🤍 на ❤️ (0мс затримки)",[3809,33753,33755],{"id":33754},"запит-відправляється-на-сервер","Запит відправляється на сервер",[3801,33757,33758],{},"POST \u002Ftrips\u002F123\u002Ffavorite",[3809,33760,33762],{"id":33761},"сервер-відповідає","Сервер відповідає",[3746,33764,33765,33771],{},[3749,33766,33767,33770],{},[3770,33768,33769],{},"Якщо 200 OK:"," нічого не робимо, UI вже правильний",[3749,33772,33773,7651,33776,33779],{},[3770,33774,33775],{},"Якщо 500 Error:",[3829,33777,33778],{},"patchResult.undo()"," відкочує зміни, іконка повертається до 🤍",[8569,33781,33782,33787,33801],{},[3801,33783,33784],{},[3770,33785,33786],{},"Коли використовувати оптимістичні оновлення:",[3746,33788,33789,33792,33795,33798],{},[3749,33790,33791],{},"✅ Прості дії з високою ймовірністю успіху (лайки, перемикачі, чекбокси)",[3749,33793,33794],{},"✅ Коли затримка відповіді сервера помітна (>200мс)",[3749,33796,33797],{},"❌ Фінансові операції (транзакції, платежі)",[3749,33799,33800],{},"❌ Критичні дії, де помилка недопустима",[3801,33802,33803,33806],{},[3770,33804,33805],{},"Золоте правило:"," Якщо відкат помилки не створює проблем — використовуйте оптимістичні оновлення!",[3793,33808],{},[3809,33810,33812],{"id":33811},"безкінечна-пагінація-infinite-scroll","Безкінечна пагінація (Infinite Scroll)",[3801,33814,33815],{},"Коли у вас сотні або тисячі записів, завантажувати їх усі одразу — погана ідея. Безкінечна пагінація завантажує дані порціями при прокручуванні.",[3822,33817,33819],{"className":3824,"code":33818,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fservices\u002FtripsApi.ts\ninterface PaginatedResponse {\n    items: Trip[]\n    nextPage: number | null\n    total: number\n}\n\nexport const tripsApi = createApi({\n    endpoints: (builder) => ({\n        getInfiniteTrips: builder.query\u003CPaginatedResponse, number>({\n            query: (page = 1) => `\u002Ftrips?page=${page}&limit=10`,\n            \n            \u002F\u002F 1. Всі сторінки зберігаються під одним ключем\n            serializeQueryArgs: ({ endpointName }) => {\n                return endpointName  \u002F\u002F Ігноруємо page у ключі кешу\n            },\n            \n            \u002F\u002F 2. Злиття нових сторінок з існуючими\n            merge: (currentCache, newResponse) => {\n                if (newResponse.nextPage === 2) {\n                    \u002F\u002F Перша сторінка — замінюємо\n                    currentCache.items = newResponse.items\n                } else {\n                    \u002F\u002F Наступні сторінки — додаємо\n                    currentCache.items.push(...newResponse.items)\n                }\n                currentCache.nextPage = newResponse.nextPage\n                currentCache.total = newResponse.total\n            },\n            \n            \u002F\u002F 3. Завжди робити запит при зміні аргументу\n            forceRefetch({ currentArg, previousArg }) {\n                return currentArg !== previousArg\n            },\n        }),\n    }),\n})\n\nexport const { useGetInfiniteTripsQuery } = tripsApi\n",[3829,33820,33821,33825,33833,33843,33855,33863,33867,33871,33885,33901,33921,33953,33957,33962,33978,33988,33992,33996,34001,34022,34040,34045,34061,34069,34074,34096,34100,34116,34132,34136,34140,34145,34159,34169,34173,34177,34181,34185,34189],{"__ignoreMap":3827},[3832,33822,33823],{"class":3834,"line":3835},[3832,33824,11022],{"class":3838},[3832,33826,33827,33829,33831],{"class":3834,"line":3842},[3832,33828,3890],{"class":3889},[3832,33830,28755],{"class":3893},[3832,33832,3897],{"class":3849},[3832,33834,33835,33837,33839,33841],{"class":3834,"line":3873},[3832,33836,28762],{"class":3853},[3832,33838,3906],{"class":3849},[3832,33840,3977],{"class":3893},[3832,33842,5653],{"class":3849},[3832,33844,33845,33847,33849,33851,33853],{"class":3834,"line":3880},[3832,33846,28773],{"class":3853},[3832,33848,3906],{"class":3849},[3832,33850,5663],{"class":3893},[3832,33852,4011],{"class":3849},[3832,33854,4391],{"class":3893},[3832,33856,33857,33859,33861],{"class":3834,"line":3886},[3832,33858,28786],{"class":3853},[3832,33860,3906],{"class":3849},[3832,33862,9238],{"class":3893},[3832,33864,33865],{"class":3834,"line":3900},[3832,33866,3945],{"class":3849},[3832,33868,33869],{"class":3834,"line":3912},[3832,33870,3877],{"emptyLinePlaceholder":3876},[3832,33872,33873,33875,33877,33879,33881,33883],{"class":3834,"line":3922},[3832,33874,4105],{"class":3845},[3832,33876,4108],{"class":3889},[3832,33878,6231],{"class":4042},[3832,33880,4114],{"class":3849},[3832,33882,6153],{"class":4117},[3832,33884,4267],{"class":3849},[3832,33886,33887,33889,33891,33893,33895,33897,33899],{"class":3834,"line":3932},[3832,33888,6288],{"class":4117},[3832,33890,4304],{"class":3853},[3832,33892,4307],{"class":3849},[3832,33894,4310],{"class":3853},[3832,33896,4313],{"class":3849},[3832,33898,4140],{"class":3889},[3832,33900,6301],{"class":3849},[3832,33902,33903,33905,33907,33909,33911,33913,33915,33917,33919],{"class":3834,"line":3942},[3832,33904,28838],{"class":3853},[3832,33906,6314],{"class":3853},[3832,33908,4183],{"class":3849},[3832,33910,6319],{"class":4117},[3832,33912,5084],{"class":3849},[3832,33914,28849],{"class":3893},[3832,33916,3857],{"class":3849},[3832,33918,5663],{"class":3893},[3832,33920,6332],{"class":3849},[3832,33922,33923,33925,33927,33929,33931,33933,33935,33937,33939,33942,33944,33946,33948,33951],{"class":3834,"line":3948},[3832,33924,6337],{"class":4117},[3832,33926,4304],{"class":3853},[3832,33928,4307],{"class":3849},[3832,33930,28866],{"class":3853},[3832,33932,4114],{"class":3849},[3832,33934,28871],{"class":5726},[3832,33936,4313],{"class":3849},[3832,33938,4140],{"class":3889},[3832,33940,33941],{"class":3869}," `\u002Ftrips?page=",[3832,33943,11249],{"class":3889},[3832,33945,28866],{"class":3853},[3832,33947,4890],{"class":3889},[3832,33949,33950],{"class":3869},"&limit=10`",[3832,33952,4072],{"class":3849},[3832,33954,33955],{"class":3834,"line":3953},[3832,33956,8518],{"class":3849},[3832,33958,33959],{"class":3834,"line":3959},[3832,33960,33961],{"class":3838},"            \u002F\u002F 1. Всі сторінки зберігаються під одним ключем\n",[3832,33963,33964,33966,33968,33970,33972,33974,33976],{"class":3834,"line":3969},[3832,33965,28903],{"class":4117},[3832,33967,4304],{"class":3853},[3832,33969,19679],{"class":3849},[3832,33971,28910],{"class":3853},[3832,33973,4981],{"class":3849},[3832,33975,4140],{"class":3889},[3832,33977,3897],{"class":3849},[3832,33979,33980,33982,33985],{"class":3834,"line":3986},[3832,33981,16712],{"class":3845},[3832,33983,33984],{"class":3853}," endpointName",[3832,33986,33987],{"class":3838},"  \u002F\u002F Ігноруємо page у ключі кешу\n",[3832,33989,33990],{"class":3834,"line":4000},[3832,33991,13923],{"class":3849},[3832,33993,33994],{"class":3834,"line":4020},[3832,33995,8518],{"class":3849},[3832,33997,33998],{"class":3834,"line":4025},[3832,33999,34000],{"class":3838},"            \u002F\u002F 2. Злиття нових сторінок з існуючими\n",[3832,34002,34003,34005,34007,34009,34011,34013,34016,34018,34020],{"class":3834,"line":4030},[3832,34004,28941],{"class":4117},[3832,34006,4304],{"class":3853},[3832,34008,4307],{"class":3849},[3832,34010,28948],{"class":3853},[3832,34012,3857],{"class":3849},[3832,34014,34015],{"class":3853},"newResponse",[3832,34017,4313],{"class":3849},[3832,34019,4140],{"class":3889},[3832,34021,3897],{"class":3849},[3832,34023,34024,34026,34028,34030,34032,34034,34036,34038],{"class":3834,"line":4036},[3832,34025,15035],{"class":3845},[3832,34027,4307],{"class":3849},[3832,34029,34015],{"class":3853},[3832,34031,4183],{"class":3849},[3832,34033,28972],{"class":3853},[3832,34035,5921],{"class":3849},[3832,34037,27721],{"class":5726},[3832,34039,4189],{"class":3849},[3832,34041,34042],{"class":3834,"line":4054},[3832,34043,34044],{"class":3838},"                    \u002F\u002F Перша сторінка — замінюємо\n",[3832,34046,34047,34049,34051,34053,34055,34057,34059],{"class":3834,"line":4063},[3832,34048,28983],{"class":3853},[3832,34050,4183],{"class":3849},[3832,34052,17471],{"class":3853},[3832,34054,4114],{"class":3849},[3832,34056,34015],{"class":3853},[3832,34058,4183],{"class":3849},[3832,34060,17525],{"class":3853},[3832,34062,34063,34065,34067],{"class":3834,"line":4075},[3832,34064,15127],{"class":3849},[3832,34066,14059],{"class":3845},[3832,34068,3897],{"class":3849},[3832,34070,34071],{"class":3834,"line":4086},[3832,34072,34073],{"class":3838},"                    \u002F\u002F Наступні сторінки — додаємо\n",[3832,34075,34076,34078,34080,34082,34084,34086,34088,34090,34092,34094],{"class":3834,"line":4091},[3832,34077,28983],{"class":3853},[3832,34079,4183],{"class":3849},[3832,34081,17471],{"class":3853},[3832,34083,4183],{"class":3849},[3832,34085,5327],{"class":4117},[3832,34087,29018],{"class":3849},[3832,34089,34015],{"class":3853},[3832,34091,4183],{"class":3849},[3832,34093,17471],{"class":3853},[3832,34095,4168],{"class":3849},[3832,34097,34098],{"class":3834,"line":4096},[3832,34099,15165],{"class":3849},[3832,34101,34102,34104,34106,34108,34110,34112,34114],{"class":3834,"line":4102},[3832,34103,29035],{"class":3853},[3832,34105,4183],{"class":3849},[3832,34107,28972],{"class":3853},[3832,34109,4114],{"class":3849},[3832,34111,34015],{"class":3853},[3832,34113,4183],{"class":3849},[3832,34115,29048],{"class":3853},[3832,34117,34118,34120,34122,34124,34126,34128,34130],{"class":3834,"line":4123},[3832,34119,29035],{"class":3853},[3832,34121,4183],{"class":3849},[3832,34123,29057],{"class":3853},[3832,34125,4114],{"class":3849},[3832,34127,34015],{"class":3853},[3832,34129,4183],{"class":3849},[3832,34131,29066],{"class":3853},[3832,34133,34134],{"class":3834,"line":4131},[3832,34135,13923],{"class":3849},[3832,34137,34138],{"class":3834,"line":4145},[3832,34139,8518],{"class":3849},[3832,34141,34142],{"class":3834,"line":4171},[3832,34143,34144],{"class":3838},"            \u002F\u002F 3. Завжди робити запит при зміні аргументу\n",[3832,34146,34147,34149,34151,34153,34155,34157],{"class":3834,"line":4192},[3832,34148,29084],{"class":4117},[3832,34150,4976],{"class":3849},[3832,34152,29089],{"class":3853},[3832,34154,3857],{"class":3849},[3832,34156,29094],{"class":3853},[3832,34158,8353],{"class":3849},[3832,34160,34161,34163,34165,34167],{"class":3834,"line":4211},[3832,34162,16712],{"class":3845},[3832,34164,29103],{"class":3853},[3832,34166,16875],{"class":3849},[3832,34168,29108],{"class":3853},[3832,34170,34171],{"class":3834,"line":4217},[3832,34172,13923],{"class":3849},[3832,34174,34175],{"class":3834,"line":4233},[3832,34176,6367],{"class":3849},[3832,34178,34179],{"class":3834,"line":4239},[3832,34180,6475],{"class":3849},[3832,34182,34183],{"class":3834,"line":4244},[3832,34184,4566],{"class":3849},[3832,34186,34187],{"class":3834,"line":4249},[3832,34188,3877],{"emptyLinePlaceholder":3876},[3832,34190,34191,34193,34195,34197,34199,34201],{"class":3834,"line":4255},[3832,34192,4105],{"class":3845},[3832,34194,4108],{"class":3889},[3832,34196,3850],{"class":3849},[3832,34198,29139],{"class":4042},[3832,34200,4748],{"class":3849},[3832,34202,6509],{"class":3853},[3801,34204,34205],{},[3770,34206,15715],{},[3822,34208,34210],{"className":4592,"code":34209,"language":4594,"meta":3827,"style":3827},"function InfiniteTripsScreen() {\n    const [page, setPage] = useState(1)\n    const { data, isFetching } = useGetInfiniteTripsQuery(page)\n    \n    const loadMore = () => {\n        if (data?.nextPage && !isFetching) {\n            setPage(data.nextPage)\n        }\n    }\n    \n    return (\n        \u003CFlatList\n            data={data?.items}\n            keyExtractor={(item) => item.id}\n            renderItem={({ item }) => \u003CTripCard trip={item} \u002F>}\n            \n            \u002F\u002F Завантаження при досягненні кінця списку\n            onEndReached={loadMore}\n            onEndReachedThreshold={0.5}  \u002F\u002F Завантажувати за 50% до кінця\n            \n            \u002F\u002F Індикатор завантаження внизу\n            ListFooterComponent={\n                isFetching ? \u003CActivityIndicator style={{ padding: 20 }} \u002F> : null\n            }\n        \u002F>\n    )\n}\n",[3829,34211,34212,34221,34244,34266,34270,34283,34302,34317,34321,34325,34329,34335,34341,34357,34381,34415,34419,34424,34438,34455,34459,34464,34473,34507,34511,34515,34519],{"__ignoreMap":3827},[3832,34213,34214,34216,34219],{"class":3834,"line":3835},[3832,34215,7416],{"class":3889},[3832,34217,34218],{"class":4117}," InfiniteTripsScreen",[3832,34220,4705],{"class":3849},[3832,34222,34223,34225,34227,34229,34231,34234,34236,34238,34240,34242],{"class":3834,"line":3842},[3832,34224,4710],{"class":3889},[3832,34226,6274],{"class":3849},[3832,34228,28866],{"class":4042},[3832,34230,3857],{"class":3849},[3832,34232,34233],{"class":4042},"setPage",[3832,34235,7437],{"class":3849},[3832,34237,7440],{"class":4117},[3832,34239,4162],{"class":3849},[3832,34241,28871],{"class":5726},[3832,34243,4168],{"class":3849},[3832,34245,34246,34248,34250,34252,34254,34256,34258,34260,34262,34264],{"class":3834,"line":3873},[3832,34247,4710],{"class":3889},[3832,34249,3850],{"class":3849},[3832,34251,6565],{"class":4042},[3832,34253,3857],{"class":3849},[3832,34255,9744],{"class":4042},[3832,34257,4748],{"class":3849},[3832,34259,29139],{"class":4117},[3832,34261,4162],{"class":3849},[3832,34263,28866],{"class":3853},[3832,34265,4168],{"class":3849},[3832,34267,34268],{"class":3834,"line":3880},[3832,34269,4724],{"class":3849},[3832,34271,34272,34274,34277,34279,34281],{"class":3834,"line":3886},[3832,34273,4710],{"class":3889},[3832,34275,34276],{"class":4117}," loadMore",[3832,34278,19297],{"class":3849},[3832,34280,4140],{"class":3889},[3832,34282,3897],{"class":3849},[3832,34284,34285,34287,34289,34291,34293,34295,34298,34300],{"class":3834,"line":3900},[3832,34286,4174],{"class":3845},[3832,34288,4307],{"class":3849},[3832,34290,6565],{"class":3853},[3832,34292,11188],{"class":3849},[3832,34294,28972],{"class":3853},[3832,34296,34297],{"class":3849}," && !",[3832,34299,9744],{"class":3853},[3832,34301,4189],{"class":3849},[3832,34303,34304,34307,34309,34311,34313,34315],{"class":3834,"line":3912},[3832,34305,34306],{"class":4117},"            setPage",[3832,34308,4162],{"class":3849},[3832,34310,6565],{"class":3853},[3832,34312,4183],{"class":3849},[3832,34314,28972],{"class":3853},[3832,34316,4168],{"class":3849},[3832,34318,34319],{"class":3834,"line":3922},[3832,34320,4214],{"class":3849},[3832,34322,34323],{"class":3834,"line":3932},[3832,34324,4236],{"class":3849},[3832,34326,34327],{"class":3834,"line":3942},[3832,34328,4724],{"class":3849},[3832,34330,34331,34333],{"class":3834,"line":3948},[3832,34332,4911],{"class":3845},[3832,34334,4914],{"class":3849},[3832,34336,34337,34339],{"class":3834,"line":3953},[3832,34338,4919],{"class":4834},[3832,34340,4922],{"class":3893},[3832,34342,34343,34345,34347,34349,34351,34353,34355],{"class":3834,"line":3959},[3832,34344,4927],{"class":4840},[3832,34346,4844],{"class":3849},[3832,34348,4885],{"class":3889},[3832,34350,6565],{"class":3853},[3832,34352,11188],{"class":4947},[3832,34354,17471],{"class":3853},[3832,34356,3945],{"class":3889},[3832,34358,34359,34361,34363,34365,34367,34369,34371,34373,34375,34377,34379],{"class":3834,"line":3969},[3832,34360,4940],{"class":4840},[3832,34362,4844],{"class":3849},[3832,34364,4885],{"class":3889},[3832,34366,4162],{"class":4947},[3832,34368,4950],{"class":3853},[3832,34370,4313],{"class":4947},[3832,34372,4140],{"class":3889},[3832,34374,4957],{"class":3853},[3832,34376,4183],{"class":4947},[3832,34378,4962],{"class":3853},[3832,34380,3945],{"class":3889},[3832,34382,34383,34385,34387,34389,34391,34393,34395,34397,34399,34401,34403,34405,34407,34409,34411,34413],{"class":3834,"line":3986},[3832,34384,4969],{"class":4840},[3832,34386,4844],{"class":3849},[3832,34388,4885],{"class":3889},[3832,34390,4976],{"class":4947},[3832,34392,4950],{"class":3853},[3832,34394,4981],{"class":4947},[3832,34396,4140],{"class":3889},[3832,34398,4835],{"class":4834},[3832,34400,17133],{"class":3893},[3832,34402,17136],{"class":4840},[3832,34404,4844],{"class":3849},[3832,34406,4885],{"class":3889},[3832,34408,4950],{"class":3853},[3832,34410,4890],{"class":3889},[3832,34412,17147],{"class":4834},[3832,34414,3945],{"class":3889},[3832,34416,34417],{"class":3834,"line":4000},[3832,34418,8518],{"class":3849},[3832,34420,34421],{"class":3834,"line":4020},[3832,34422,34423],{"class":3838},"            \u002F\u002F Завантаження при досягненні кінця списку\n",[3832,34425,34426,34429,34431,34433,34436],{"class":3834,"line":4025},[3832,34427,34428],{"class":4840},"            onEndReached",[3832,34430,4844],{"class":3849},[3832,34432,4885],{"class":3889},[3832,34434,34435],{"class":3853},"loadMore",[3832,34437,3945],{"class":3889},[3832,34439,34440,34443,34445,34447,34450,34452],{"class":3834,"line":4030},[3832,34441,34442],{"class":4840},"            onEndReachedThreshold",[3832,34444,4844],{"class":3849},[3832,34446,4885],{"class":3889},[3832,34448,34449],{"class":5726},"0.5",[3832,34451,4890],{"class":3889},[3832,34453,34454],{"class":3838},"  \u002F\u002F Завантажувати за 50% до кінця\n",[3832,34456,34457],{"class":3834,"line":4036},[3832,34458,8518],{"class":3849},[3832,34460,34461],{"class":3834,"line":4054},[3832,34462,34463],{"class":3838},"            \u002F\u002F Індикатор завантаження внизу\n",[3832,34465,34466,34469,34471],{"class":3834,"line":4063},[3832,34467,34468],{"class":4840},"            ListFooterComponent",[3832,34470,4844],{"class":3849},[3832,34472,11782],{"class":3889},[3832,34474,34475,34478,34480,34482,34484,34486,34488,34490,34492,34494,34496,34498,34500,34502,34504],{"class":3834,"line":4075},[3832,34476,34477],{"class":3853},"                isFetching",[3832,34479,8488],{"class":3849},[3832,34481,4835],{"class":4834},[3832,34483,4645],{"class":3893},[3832,34485,8467],{"class":4840},[3832,34487,4844],{"class":3849},[3832,34489,4885],{"class":3889},[3832,34491,8474],{"class":4947},[3832,34493,20632],{"class":3853},[3832,34495,10440],{"class":5726},[3832,34497,8500],{"class":4947},[3832,34499,4890],{"class":3889},[3832,34501,17147],{"class":4834},[3832,34503,8494],{"class":3849},[3832,34505,34506],{"class":3889}," null\n",[3832,34508,34509],{"class":3834,"line":4086},[3832,34510,11521],{"class":3889},[3832,34512,34513],{"class":3834,"line":4091},[3832,34514,5013],{"class":4834},[3832,34516,34517],{"class":3834,"line":4096},[3832,34518,5018],{"class":3849},[3832,34520,34521],{"class":3834,"line":4102},[3832,34522,3945],{"class":3849},[3801,34524,34525],{},[3770,34526,12046],{},[5430,34528,34529,34533,34539,34543,34552,34556,34565,34569],{},[3809,34530,34532],{"id":34531},"перший-рендер","Перший рендер",[3801,34534,34535,34538],{},[3829,34536,34537],{},"useGetInfiniteTripsQuery(1)"," → Завантажує сторінку 1 (10 поїздок)",[3809,34540,34542],{"id":34541},"користувач-прокручує-вниз","Користувач прокручує вниз",[3801,34544,34545,34548,34549],{},[3829,34546,34547],{},"onEndReached"," спрацьовує → ",[3829,34550,34551],{},"setPage(2)",[3809,34553,34555],{"id":34554},"завантаження-сторінки-2","Завантаження сторінки 2",[3801,34557,34558,8584,34561,34564],{},[3829,34559,34560],{},"useGetInfiniteTripsQuery(2)",[3829,34562,34563],{},"merge()"," додає 10 нових поїздок до існуючих",[3809,34566,34568],{"id":34567},"результат","Результат",[3801,34570,34571],{},"Список тепер містить 20 поїздок (сторінка 1 + сторінка 2)",[3793,34573],{},[3809,34575,34577],{"id":34576},"websockets-оновлення-у-реальному-часі","WebSockets: Оновлення у реальному часі",[3801,34579,34580],{},"Якщо дані на сервері змінюються постійно (наприклад, координати водія на карті), використовуйте WebSocket підключення.",[3822,34582,34584],{"className":3824,"code":34583,"language":3826,"meta":3827,"style":3827},"\u002F\u002F src\u002Fservices\u002FliveTrackingApi.ts\nexport const liveTrackingApi = createApi({\n    endpoints: (builder) => ({\n        getLiveLocation: builder.query\u003C{ lat: number; lng: number }, string>({\n            query: (driverId) => `\u002Fdrivers\u002F${driverId}\u002Flocation`,\n            \n            \u002F\u002F Lifecycle хук для WebSocket підключення\n            async onCacheEntryAdded(\n                driverId,\n                { updateCachedData, cacheDataLoaded, cacheEntryRemoved }\n            ) {\n                \u002F\u002F Створюємо WebSocket з'єднання\n                const ws = new WebSocket(`wss:\u002F\u002Fapi.example.com\u002Fdrivers\u002F${driverId}\u002Flive`)\n                \n                try {\n                    \u002F\u002F Чекаємо поки початковий HTTP-запит завершиться\n                    await cacheDataLoaded\n                    \n                    \u002F\u002F Слухаємо оновлення з WebSocket\n                    ws.onmessage = (event) => {\n                        const newLocation = JSON.parse(event.data)\n                        \n                        \u002F\u002F Оновлюємо кеш RTK Query\n                        updateCachedData((draft) => {\n                            draft.lat = newLocation.lat\n                            draft.lng = newLocation.lng\n                        })\n                    }\n                } catch {\n                    \u002F\u002F Помилка початкового завантаження\n                }\n                \n                \u002F\u002F Коли компонент розмонтується — закриваємо WebSocket\n                await cacheEntryRemoved\n                ws.close()\n            },\n        }),\n    }),\n})\n",[3829,34585,34586,34591,34606,34622,34657,34686,34690,34695,34703,34710,34726,34731,34735,34762,34766,34772,34777,34783,34787,34792,34810,34835,34840,34845,34859,34878,34895,34899,34903,34911,34916,34920,34924,34929,34935,34945,34949,34953,34957],{"__ignoreMap":3827},[3832,34587,34588],{"class":3834,"line":3835},[3832,34589,34590],{"class":3838},"\u002F\u002F src\u002Fservices\u002FliveTrackingApi.ts\n",[3832,34592,34593,34595,34597,34600,34602,34604],{"class":3834,"line":3842},[3832,34594,4105],{"class":3845},[3832,34596,4108],{"class":3889},[3832,34598,34599],{"class":4042}," liveTrackingApi",[3832,34601,4114],{"class":3849},[3832,34603,6153],{"class":4117},[3832,34605,4267],{"class":3849},[3832,34607,34608,34610,34612,34614,34616,34618,34620],{"class":3834,"line":3873},[3832,34609,6288],{"class":4117},[3832,34611,4304],{"class":3853},[3832,34613,4307],{"class":3849},[3832,34615,4310],{"class":3853},[3832,34617,4313],{"class":3849},[3832,34619,4140],{"class":3889},[3832,34621,6301],{"class":3849},[3832,34623,34624,34627,34629,34631,34633,34635,34638,34640,34642,34644,34647,34649,34651,34653,34655],{"class":3834,"line":3880},[3832,34625,34626],{"class":3853},"        getLiveLocation:",[3832,34628,6314],{"class":3853},[3832,34630,4183],{"class":3849},[3832,34632,6319],{"class":4117},[3832,34634,12498],{"class":3849},[3832,34636,34637],{"class":3853},"lat",[3832,34639,3906],{"class":3849},[3832,34641,5663],{"class":3893},[3832,34643,12378],{"class":3849},[3832,34645,34646],{"class":3853},"lng",[3832,34648,3906],{"class":3849},[3832,34650,5663],{"class":3893},[3832,34652,22297],{"class":3849},[3832,34654,4008],{"class":3893},[3832,34656,6332],{"class":3849},[3832,34658,34659,34661,34663,34665,34668,34670,34672,34675,34677,34679,34681,34684],{"class":3834,"line":3886},[3832,34660,6337],{"class":4117},[3832,34662,4304],{"class":3853},[3832,34664,4307],{"class":3849},[3832,34666,34667],{"class":3853},"driverId",[3832,34669,4313],{"class":3849},[3832,34671,4140],{"class":3889},[3832,34673,34674],{"class":3869}," `\u002Fdrivers\u002F",[3832,34676,11249],{"class":3889},[3832,34678,34667],{"class":3853},[3832,34680,4890],{"class":3889},[3832,34682,34683],{"class":3869},"\u002Flocation`",[3832,34685,4072],{"class":3849},[3832,34687,34688],{"class":3834,"line":3900},[3832,34689,8518],{"class":3849},[3832,34691,34692],{"class":3834,"line":3912},[3832,34693,34694],{"class":3838},"            \u002F\u002F Lifecycle хук для WebSocket підключення\n",[3832,34696,34697,34699,34701],{"class":3834,"line":3922},[3832,34698,28038],{"class":3889},[3832,34700,28434],{"class":4117},[3832,34702,4120],{"class":3849},[3832,34704,34705,34708],{"class":3834,"line":3932},[3832,34706,34707],{"class":3853},"                driverId",[3832,34709,4072],{"class":3849},[3832,34711,34712,34714,34716,34718,34720,34722,34724],{"class":3834,"line":3942},[3832,34713,21893],{"class":3849},[3832,34715,28443],{"class":3853},[3832,34717,3857],{"class":3849},[3832,34719,28448],{"class":3853},[3832,34721,3857],{"class":3849},[3832,34723,28453],{"class":3853},[3832,34725,11831],{"class":3849},[3832,34727,34728],{"class":3834,"line":3948},[3832,34729,34730],{"class":3849},"            ) {\n",[3832,34732,34733],{"class":3834,"line":3953},[3832,34734,28460],{"class":3838},[3832,34736,34737,34739,34741,34743,34745,34747,34749,34752,34754,34756,34758,34760],{"class":3834,"line":3959},[3832,34738,14926],{"class":3889},[3832,34740,28467],{"class":4042},[3832,34742,4114],{"class":3849},[3832,34744,7494],{"class":3889},[3832,34746,28474],{"class":4117},[3832,34748,4162],{"class":3849},[3832,34750,34751],{"class":3869},"`wss:\u002F\u002Fapi.example.com\u002Fdrivers\u002F",[3832,34753,11249],{"class":3889},[3832,34755,34667],{"class":3853},[3832,34757,4890],{"class":3889},[3832,34759,28488],{"class":3869},[3832,34761,4168],{"class":3849},[3832,34763,34764],{"class":3834,"line":3969},[3832,34765,14921],{"class":3849},[3832,34767,34768,34770],{"class":3834,"line":3986},[3832,34769,28207],{"class":3845},[3832,34771,3897],{"class":3849},[3832,34773,34774],{"class":3834,"line":4000},[3832,34775,34776],{"class":3838},"                    \u002F\u002F Чекаємо поки початковий HTTP-запит завершиться\n",[3832,34778,34779,34781],{"class":3834,"line":4020},[3832,34780,28219],{"class":3845},[3832,34782,28512],{"class":3853},[3832,34784,34785],{"class":3834,"line":4025},[3832,34786,15092],{"class":3849},[3832,34788,34789],{"class":3834,"line":4030},[3832,34790,34791],{"class":3838},"                    \u002F\u002F Слухаємо оновлення з WebSocket\n",[3832,34793,34794,34796,34798,34800,34802,34804,34806,34808],{"class":3834,"line":4036},[3832,34795,28526],{"class":3853},[3832,34797,4183],{"class":3849},[3832,34799,28531],{"class":4117},[3832,34801,11450],{"class":3849},[3832,34803,28536],{"class":3853},[3832,34805,4313],{"class":3849},[3832,34807,4140],{"class":3889},[3832,34809,3897],{"class":3849},[3832,34811,34812,34814,34817,34819,34821,34823,34825,34827,34829,34831,34833],{"class":3834,"line":4054},[3832,34813,28120],{"class":3889},[3832,34815,34816],{"class":4042}," newLocation",[3832,34818,4114],{"class":3849},[3832,34820,28554],{"class":4042},[3832,34822,4183],{"class":3849},[3832,34824,28559],{"class":4117},[3832,34826,4162],{"class":3849},[3832,34828,28536],{"class":3853},[3832,34830,4183],{"class":3849},[3832,34832,6565],{"class":3853},[3832,34834,4168],{"class":3849},[3832,34836,34837],{"class":3834,"line":4063},[3832,34838,34839],{"class":3849},"                        \n",[3832,34841,34842],{"class":3834,"line":4075},[3832,34843,34844],{"class":3838},"                        \u002F\u002F Оновлюємо кеш RTK Query\n",[3832,34846,34847,34849,34851,34853,34855,34857],{"class":3834,"line":4086},[3832,34848,28579],{"class":4117},[3832,34850,4753],{"class":3849},[3832,34852,28105],{"class":3853},[3832,34854,4313],{"class":3849},[3832,34856,4140],{"class":3889},[3832,34858,3897],{"class":3849},[3832,34860,34861,34864,34866,34868,34870,34873,34875],{"class":3834,"line":4091},[3832,34862,34863],{"class":3853},"                            draft",[3832,34865,4183],{"class":3849},[3832,34867,34637],{"class":3853},[3832,34869,4114],{"class":3849},[3832,34871,34872],{"class":3853},"newLocation",[3832,34874,4183],{"class":3849},[3832,34876,34877],{"class":3853},"lat\n",[3832,34879,34880,34882,34884,34886,34888,34890,34892],{"class":3834,"line":4096},[3832,34881,34863],{"class":3853},[3832,34883,4183],{"class":3849},[3832,34885,34646],{"class":3853},[3832,34887,4114],{"class":3849},[3832,34889,34872],{"class":3853},[3832,34891,4183],{"class":3849},[3832,34893,34894],{"class":3853},"lng\n",[3832,34896,34897],{"class":3834,"line":4102},[3832,34898,28615],{"class":3849},[3832,34900,34901],{"class":3834,"line":4123},[3832,34902,28620],{"class":3849},[3832,34904,34905,34907,34909],{"class":3834,"line":4131},[3832,34906,15127],{"class":3849},[3832,34908,20571],{"class":3845},[3832,34910,3897],{"class":3849},[3832,34912,34913],{"class":3834,"line":4145},[3832,34914,34915],{"class":3838},"                    \u002F\u002F Помилка початкового завантаження\n",[3832,34917,34918],{"class":3834,"line":4171},[3832,34919,15165],{"class":3849},[3832,34921,34922],{"class":3834,"line":4192},[3832,34923,14921],{"class":3849},[3832,34925,34926],{"class":3834,"line":4211},[3832,34927,34928],{"class":3838},"                \u002F\u002F Коли компонент розмонтується — закриваємо WebSocket\n",[3832,34930,34931,34933],{"class":3834,"line":4217},[3832,34932,28651],{"class":3845},[3832,34934,28654],{"class":3853},[3832,34936,34937,34939,34941,34943],{"class":3834,"line":4233},[3832,34938,28659],{"class":3853},[3832,34940,4183],{"class":3849},[3832,34942,28664],{"class":4117},[3832,34944,4230],{"class":3849},[3832,34946,34947],{"class":3834,"line":4239},[3832,34948,13923],{"class":3849},[3832,34950,34951],{"class":3834,"line":4244},[3832,34952,6367],{"class":3849},[3832,34954,34955],{"class":3834,"line":4249},[3832,34956,6475],{"class":3849},[3832,34958,34959],{"class":3834,"line":4255},[3832,34960,4566],{"class":3849},[3801,34962,34963],{},[3770,34964,16039],{},[3822,34966,34968],{"className":4592,"code":34967,"language":4594,"meta":3827,"style":3827},"function DriverMapScreen({ driverId }) {\n    \u002F\u002F Початкове завантаження через HTTP, потім оновлення через WebSocket\n    const { data: location } = useGetLiveLocationQuery(driverId)\n    \n    return (\n        \u003CMapView>\n            {location && (\n                \u003CMarker\n                    coordinate={{\n                        latitude: location.lat,\n                        longitude: location.lng,\n                    }}\n                \u002F>\n            )}\n        \u003C\u002FMapView>\n    )\n}\n",[3829,34969,34970,34983,34988,35012,35016,35022,35031,35041,35048,35059,35073,35086,35093,35097,35103,35111,35115],{"__ignoreMap":3827},[3832,34971,34972,34974,34977,34979,34981],{"class":3834,"line":3835},[3832,34973,7416],{"class":3889},[3832,34975,34976],{"class":4117}," DriverMapScreen",[3832,34978,4976],{"class":3849},[3832,34980,34667],{"class":3853},[3832,34982,8353],{"class":3849},[3832,34984,34985],{"class":3834,"line":3842},[3832,34986,34987],{"class":3838},"    \u002F\u002F Початкове завантаження через HTTP, потім оновлення через WebSocket\n",[3832,34989,34990,34992,34994,34996,34998,35001,35003,35006,35008,35010],{"class":3834,"line":3873},[3832,34991,4710],{"class":3889},[3832,34993,3850],{"class":3849},[3832,34995,6565],{"class":3853},[3832,34997,3906],{"class":3849},[3832,34999,35000],{"class":4042},"location",[3832,35002,4748],{"class":3849},[3832,35004,35005],{"class":4117},"useGetLiveLocationQuery",[3832,35007,4162],{"class":3849},[3832,35009,34667],{"class":3853},[3832,35011,4168],{"class":3849},[3832,35013,35014],{"class":3834,"line":3880},[3832,35015,4724],{"class":3849},[3832,35017,35018,35020],{"class":3834,"line":3886},[3832,35019,4911],{"class":3845},[3832,35021,4914],{"class":3849},[3832,35023,35024,35026,35029],{"class":3834,"line":3900},[3832,35025,4919],{"class":4834},[3832,35027,35028],{"class":3893},"MapView",[3832,35030,4898],{"class":4834},[3832,35032,35033,35035,35037,35039],{"class":3834,"line":3912},[3832,35034,7586],{"class":3889},[3832,35036,35000],{"class":3853},[3832,35038,18261],{"class":3849},[3832,35040,4914],{"class":4947},[3832,35042,35043,35045],{"class":3834,"line":3922},[3832,35044,9984],{"class":4834},[3832,35046,35047],{"class":3893},"Marker\n",[3832,35049,35050,35053,35055,35057],{"class":3834,"line":3932},[3832,35051,35052],{"class":4840},"                    coordinate",[3832,35054,4844],{"class":3849},[3832,35056,4885],{"class":3889},[3832,35058,11782],{"class":4947},[3832,35060,35061,35064,35067,35069,35071],{"class":3834,"line":3942},[3832,35062,35063],{"class":3853},"                        latitude:",[3832,35065,35066],{"class":3853}," location",[3832,35068,4183],{"class":4947},[3832,35070,34637],{"class":3853},[3832,35072,4072],{"class":4947},[3832,35074,35075,35078,35080,35082,35084],{"class":3834,"line":3948},[3832,35076,35077],{"class":3853},"                        longitude:",[3832,35079,35066],{"class":3853},[3832,35081,4183],{"class":4947},[3832,35083,34646],{"class":3853},[3832,35085,4072],{"class":4947},[3832,35087,35088,35091],{"class":3834,"line":3953},[3832,35089,35090],{"class":4947},"                    }",[3832,35092,3945],{"class":3889},[3832,35094,35095],{"class":3834,"line":3959},[3832,35096,30429],{"class":4834},[3832,35098,35099,35101],{"class":3834,"line":3969},[3832,35100,10360],{"class":4947},[3832,35102,3945],{"class":3889},[3832,35104,35105,35107,35109],{"class":3834,"line":3986},[3832,35106,7596],{"class":4834},[3832,35108,35028],{"class":3893},[3832,35110,4898],{"class":4834},[3832,35112,35113],{"class":3834,"line":4000},[3832,35114,5018],{"class":3849},[3832,35116,35117],{"class":3834,"line":4020},[3832,35118,3945],{"class":3849},[3801,35120,35121],{},[3770,35122,12229],{},[5430,35124,35125,35128,35135,35139,35145,35149,35152,35156,35159,35163],{},[3809,35126,10763],{"id":35127},"компонент-монтується-1",[3801,35129,35130,35131,35134],{},"HTTP GET ",[3829,35132,35133],{},"\u002Fdrivers\u002F123\u002Flocation"," → отримує початкові координати",[3809,35136,35138],{"id":35137},"websocket-підключається","WebSocket підключається",[3801,35140,35141,35144],{},[3829,35142,35143],{},"new WebSocket(...)"," → встановлює з'єднання",[3809,35146,35148],{"id":35147},"сервер-надсилає-оновлення","Сервер надсилає оновлення",[3801,35150,35151],{},"Кожні 2 секунди → нові координати через WebSocket",[3809,35153,35155],{"id":35154},"updatecacheddata-оновлює-кеш","updateCachedData() оновлює кеш",[3801,35157,35158],{},"Маркер на карті переміщується плавно",[3809,35160,35162],{"id":35161},"компонент-розмонтується","Компонент розмонтується",[3801,35164,35165,35168],{},[3829,35166,35167],{},"ws.close()"," → WebSocket закривається автоматично",[3793,35170],{},[3796,35172,35174],{"id":35173},"підсумок-і-наступні-кроки","Підсумок і наступні кроки",[3738,35176,35177,35213,35249],{},[3741,35178,35181],{"icon":35179,"title":35180},"i-lucide-check-circle","🎯 Що ви опанували",[3746,35182,35183,35186,35192,35195,35198,35201,35204,35207,35210],{},[3749,35184,35185],{},"Різницю між клієнтським та серверним станом",[3749,35187,35188,35189,35191],{},"Налаштування ",[3829,35190,6153],{}," та інтеграцію з Redux",[3749,35193,35194],{},"Query endpoints для читання даних (з параметрами, фільтрами, transformResponse)",[3749,35196,35197],{},"Mutation endpoints для зміни даних (POST, PATCH, DELETE)",[3749,35199,35200],{},"Систему тегів для автоматичної інвалідації кешу",[3749,35202,35203],{},"JWT авторизацію з Refresh Token через Mutex",[3749,35205,35206],{},"Оптимістичні оновлення для миттєвого UX",[3749,35208,35209],{},"Безкінечну пагінацію для великих списків",[3749,35211,35212],{},"WebSocket інтеграцію для реального часу",[3741,35214,35216],{"icon":15,"title":35215},"📚 Рекомендовані ресурси",[3746,35217,35218,35226,35234,35242],{},[3749,35219,35220],{},[17606,35221,35225],{"href":35222,"rel":35223},"https:\u002F\u002Fredux-toolkit.js.org\u002Frtk-query\u002Foverview",[35224],"nofollow","Офіційна документація RTK Query",[3749,35227,35228,35233],{},[17606,35229,35232],{"href":35230,"rel":35231},"https:\u002F\u002Fgithub.com\u002Freduxjs\u002Fredux-devtools",[35224],"Redux DevTools"," — для дебагу стану та тегів",[3749,35235,35236,35241],{},[17606,35237,35240],{"href":35238,"rel":35239},"https:\u002F\u002Fredux-toolkit.js.org\u002Frtk-query\u002Fusage\u002Fcode-generation",[35224],"RTK Query Codegen"," — генерація з OpenAPI",[3749,35243,35244],{},[17606,35245,35248],{"href":35246,"rel":35247},"https:\u002F\u002Fgithub.com\u002Freduxjs\u002Fredux-toolkit\u002Ftree\u002Fmaster\u002Fexamples",[35224],"Приклади RTK Query",[3741,35250,35253],{"icon":35251,"title":35252},"i-lucide-rocket","🚀 Практичні завдання",[12048,35254,35255,35261,35267],{},[3749,35256,35257,35260],{},[3770,35258,35259],{},"Базовий рівень:"," Додайте пошук поїздок з debounce (затримка 300мс)",[3749,35262,35263,35266],{},[3770,35264,35265],{},"Середній рівень:"," Реалізуйте оптимістичне редагування назви поїздки",[3749,35268,35269,35272],{},[3770,35270,35271],{},"Просунутий рівень:"," Створіть систему тегів для коментарів з умовною інвалідацією",[3793,35274],{},[3796,35276,32976],{"id":35277},"поширені-запитання-faq-1",[8777,35279,35280,35313,35412,35581],{},[8780,35281,35283,35290,35293,35310],{"icon":8782,"label":35282},"🤔 Чи можна використовувати RTK Query без Redux?",[3801,35284,35285,35286,35289],{},"Технічно ні — RTK Query працює поверх Redux Toolkit. Але це не означає, що вам потрібно використовувати Redux для ",[3770,35287,35288],{},"всього"," стану!",[3801,35291,35292],{},"Типовий підхід:",[3746,35294,35295,35300,35305],{},[3749,35296,35297,35299],{},[3770,35298,6131],{}," — для серверного стану (запити до API)",[3749,35301,35302,35304],{},[3770,35303,2203],{}," — для глобального клієнтського стану (авторизація, налаштування)",[3749,35306,35307,35309],{},[3770,35308,7440],{}," — для локального стану компонентів (форми, UI елементи)",[3801,35311,35312],{},"Якщо вам зовсім не потрібен Redux — розгляньте TanStack Query або SWR.",[8780,35314,35316,35323,35337,35347,35351],{"icon":8782,"label":35315},"🤔 Як працює кешування? Скільки часу живуть дані?",[3801,35317,35318,35319,35322],{},"RTK Query використовує ",[3770,35320,35321],{},"двох-рівневу систему"," кешування:",[12048,35324,35325,35331],{},[3749,35326,35327,35330],{},[3770,35328,35329],{},"Активний кеш"," — поки хоч один компонент підписаний на дані",[3749,35332,35333,35336],{},[3770,35334,35335],{},"Неактивний кеш"," — після того як останній компонент відписався",[3801,35338,35339,35340,35342,35343,35346],{},"Параметр ",[3829,35341,12217],{}," (за замовчуванням 60 секунд) визначає, скільки зберігати ",[3770,35344,35345],{},"неактивний"," кеш.",[3801,35348,35349],{},[3770,35350,12207],{},[3822,35352,35354],{"className":3824,"code":35353,"language":3826,"meta":3827,"style":3827},"\u002F\u002F Користувач відкриває екран списку\nuseGetTripsQuery()  \u002F\u002F Активний кеш\n\n\u002F\u002F Користувач переходить на інший екран\n\u002F\u002F Активна підписка зникає → таймер 60 сек запускається\n\n\u002F\u002F Якщо користувач повернеться протягом 60 сек:\n\u002F\u002F Дані все ще у кеші → миттєвий показ\n\n\u002F\u002F Якщо пройде > 60 сек:\n\u002F\u002F Кеш очищено → новий запит при поверненні\n",[3829,35355,35356,35361,35370,35374,35379,35384,35388,35393,35398,35402,35407],{"__ignoreMap":3827},[3832,35357,35358],{"class":3834,"line":3835},[3832,35359,35360],{"class":3838},"\u002F\u002F Користувач відкриває екран списку\n",[3832,35362,35363,35365,35367],{"class":3834,"line":3842},[3832,35364,6499],{"class":4117},[3832,35366,20523],{"class":3849},[3832,35368,35369],{"class":3838},"\u002F\u002F Активний кеш\n",[3832,35371,35372],{"class":3834,"line":3873},[3832,35373,3877],{"emptyLinePlaceholder":3876},[3832,35375,35376],{"class":3834,"line":3880},[3832,35377,35378],{"class":3838},"\u002F\u002F Користувач переходить на інший екран\n",[3832,35380,35381],{"class":3834,"line":3886},[3832,35382,35383],{"class":3838},"\u002F\u002F Активна підписка зникає → таймер 60 сек запускається\n",[3832,35385,35386],{"class":3834,"line":3900},[3832,35387,3877],{"emptyLinePlaceholder":3876},[3832,35389,35390],{"class":3834,"line":3912},[3832,35391,35392],{"class":3838},"\u002F\u002F Якщо користувач повернеться протягом 60 сек:\n",[3832,35394,35395],{"class":3834,"line":3922},[3832,35396,35397],{"class":3838},"\u002F\u002F Дані все ще у кеші → миттєвий показ\n",[3832,35399,35400],{"class":3834,"line":3932},[3832,35401,3877],{"emptyLinePlaceholder":3876},[3832,35403,35404],{"class":3834,"line":3942},[3832,35405,35406],{"class":3838},"\u002F\u002F Якщо пройде > 60 сек:\n",[3832,35408,35409],{"class":3834,"line":3948},[3832,35410,35411],{"class":3838},"\u002F\u002F Кеш очищено → новий запит при поверненні\n",[8780,35413,35415,35421,35429,35438,35551,35557,35563],{"icon":8782,"label":35414},"🤔 Як дебагити проблеми з тегами?",[3801,35416,35417,35420],{},[3770,35418,35419],{},"Крок 1:"," Відкрийте Redux DevTools",[3801,35422,35423,35426,35427,9460],{},[3770,35424,35425],{},"Крок 2:"," Перейдіть у вкладку State → знайдіть ваш API (наприклад, ",[3829,35428,24368],{},[3801,35430,35431,35434,35435,4304],{},[3770,35432,35433],{},"Крок 3:"," Перевірте ",[3829,35436,35437],{},"queries",[3822,35439,35441],{"className":27571,"code":35440,"language":4227,"meta":3827,"style":3827},"{\n    \"tripsApi\": {\n        \"queries\": {\n            \"getTrips(undefined)\": {\n                \"providedTags\": [\n                    { \"type\": \"Trip\", \"id\": \"1\" },\n                    { \"type\": \"Trip\", \"id\": \"2\" },\n                    { \"type\": \"Trip\", \"id\": \"LIST\" }\n                ]\n            }\n        }\n    }\n}\n",[3829,35442,35443,35447,35453,35459,35465,35471,35491,35511,35531,35535,35539,35543,35547],{"__ignoreMap":3827},[3832,35444,35445],{"class":3834,"line":3835},[3832,35446,11782],{"class":3849},[3832,35448,35449,35451],{"class":3834,"line":3842},[3832,35450,27584],{"class":27583},[3832,35452,17308],{"class":3849},[3832,35454,35455,35457],{"class":3834,"line":3873},[3832,35456,27591],{"class":27583},[3832,35458,17308],{"class":3849},[3832,35460,35461,35463],{"class":3834,"line":3880},[3832,35462,27598],{"class":27583},[3832,35464,17308],{"class":3849},[3832,35466,35467,35469],{"class":3834,"line":3886},[3832,35468,27630],{"class":27583},[3832,35470,27633],{"class":3849},[3832,35472,35473,35475,35477,35479,35481,35483,35485,35487,35489],{"class":3834,"line":3900},[3832,35474,27638],{"class":3849},[3832,35476,27641],{"class":27583},[3832,35478,3906],{"class":3849},[3832,35480,27646],{"class":3869},[3832,35482,3857],{"class":3849},[3832,35484,27651],{"class":27583},[3832,35486,3906],{"class":3849},[3832,35488,27656],{"class":3869},[3832,35490,5145],{"class":3849},[3832,35492,35493,35495,35497,35499,35501,35503,35505,35507,35509],{"class":3834,"line":3912},[3832,35494,27638],{"class":3849},[3832,35496,27641],{"class":27583},[3832,35498,3906],{"class":3849},[3832,35500,27646],{"class":3869},[3832,35502,3857],{"class":3849},[3832,35504,27651],{"class":27583},[3832,35506,3906],{"class":3849},[3832,35508,27677],{"class":3869},[3832,35510,5145],{"class":3849},[3832,35512,35513,35515,35517,35519,35521,35523,35525,35527,35529],{"class":3834,"line":3922},[3832,35514,27638],{"class":3849},[3832,35516,27641],{"class":27583},[3832,35518,3906],{"class":3849},[3832,35520,27646],{"class":3869},[3832,35522,3857],{"class":3849},[3832,35524,27651],{"class":27583},[3832,35526,3906],{"class":3849},[3832,35528,27698],{"class":3869},[3832,35530,11831],{"class":3849},[3832,35532,35533],{"class":3834,"line":3932},[3832,35534,27705],{"class":3849},[3832,35536,35537],{"class":3834,"line":3942},[3832,35538,11521],{"class":3849},[3832,35540,35541],{"class":3834,"line":3948},[3832,35542,4214],{"class":3849},[3832,35544,35545],{"class":3834,"line":3953},[3832,35546,4236],{"class":3849},[3832,35548,35549],{"class":3834,"line":3959},[3832,35550,3945],{"class":3849},[3801,35552,35553,35556],{},[3770,35554,35555],{},"Крок 4:"," Виконайте мутацію та перевірте, чи спрацювала інвалідація",[3801,35558,35559,35562],{},[3770,35560,35561],{},"Крок 5:"," Якщо інвалідація не працює — перевірте:",[3746,35564,35565,35571,35578],{},[3749,35566,35567,35568,9460],{},"Чи співпадають типи тегів (",[3829,35569,35570],{},"tagTypes: ['Trip']",[3749,35572,35573,35574,18007,35576],{},"Чи правильно вказані теги у ",[3829,35575,12059],{},[3829,35577,12068],{},[3749,35579,35580],{},"Чи активна підписка (компонент змонтований)",[8780,35582,35584,35587,35592,35661,35666,35692,35697,35736,35741],{"icon":8782,"label":35583},"🤔 Що робити з помилками мережі (timeout, offline)?",[3801,35585,35586],{},"RTK Query автоматично обробляє багато випадків:",[3801,35588,35589],{},[3770,35590,35591],{},"1. Відсутність інтернету при завантаженні:",[3822,35593,35595],{"className":4592,"code":35594,"language":4594,"meta":3827,"style":3827},"const { data, error, isError } = useGetTripsQuery()\n\nif (isError) {\n    \u002F\u002F error містить інформацію про помилку\n    return \u003CText>Немає з'єднання з інтернетом\u003C\u002FText>\n}\n",[3829,35596,35597,35619,35623,35633,35638,35657],{"__ignoreMap":3827},[3832,35598,35599,35601,35603,35605,35607,35609,35611,35613,35615,35617],{"class":3834,"line":3835},[3832,35600,4039],{"class":3889},[3832,35602,3850],{"class":3849},[3832,35604,6565],{"class":4042},[3832,35606,3857],{"class":3849},[3832,35608,4386],{"class":4042},[3832,35610,3857],{"class":3849},[3832,35612,18517],{"class":4042},[3832,35614,4748],{"class":3849},[3832,35616,6499],{"class":4117},[3832,35618,4230],{"class":3849},[3832,35620,35621],{"class":3834,"line":3842},[3832,35622,3877],{"emptyLinePlaceholder":3876},[3832,35624,35625,35627,35629,35631],{"class":3834,"line":3873},[3832,35626,18117],{"class":3845},[3832,35628,4307],{"class":3849},[3832,35630,18517],{"class":3853},[3832,35632,4189],{"class":3849},[3832,35634,35635],{"class":3834,"line":3880},[3832,35636,35637],{"class":3838},"    \u002F\u002F error містить інформацію про помилку\n",[3832,35639,35640,35642,35644,35646,35648,35651,35653,35655],{"class":3834,"line":3886},[3832,35641,4911],{"class":3845},[3832,35643,4835],{"class":4834},[3832,35645,4635],{"class":3893},[3832,35647,4879],{"class":4834},[3832,35649,35650],{"class":3849},"Немає з'єднання з інтернетом",[3832,35652,4893],{"class":4834},[3832,35654,4635],{"class":3893},[3832,35656,4898],{"class":4834},[3832,35658,35659],{"class":3834,"line":3900},[3832,35660,3945],{"class":3849},[3801,35662,35663],{},[3770,35664,35665],{},"2. Автоматичне повторне підключення:",[3822,35667,35669],{"className":3824,"code":35668,"language":3826,"meta":3827,"style":3827},"createApi({\n    refetchOnReconnect: true,  \u002F\u002F Автоматично оновити при відновленні мережі\n})\n",[3829,35670,35671,35677,35688],{"__ignoreMap":3827},[3832,35672,35673,35675],{"class":3834,"line":3835},[3832,35674,6153],{"class":4117},[3832,35676,4267],{"class":3849},[3832,35678,35679,35681,35683,35685],{"class":3834,"line":3842},[3832,35680,11638],{"class":3853},[3832,35682,11622],{"class":3889},[3832,35684,11662],{"class":3849},[3832,35686,35687],{"class":3838},"\u002F\u002F Автоматично оновити при відновленні мережі\n",[3832,35689,35690],{"class":3834,"line":3873},[3832,35691,4566],{"class":3849},[3801,35693,35694],{},[3770,35695,35696],{},"3. Кастомна обробка таймаутів:",[3822,35698,35700],{"className":3824,"code":35699,"language":3826,"meta":3827,"style":3827},"baseQuery: fetchBaseQuery({\n    baseUrl: '...',\n    timeout: 10000,  \u002F\u002F 10 секунд\n})\n",[3829,35701,35702,35712,35720,35732],{"__ignoreMap":3827},[3832,35703,35704,35706,35708,35710],{"class":3834,"line":3835},[3832,35705,8840],{"class":5204},[3832,35707,3906],{"class":3849},[3832,35709,6158],{"class":4117},[3832,35711,4267],{"class":3849},[3832,35713,35714,35716,35718],{"class":3834,"line":3842},[3832,35715,13553],{"class":3853},[3832,35717,30448],{"class":3869},[3832,35719,4072],{"class":3849},[3832,35721,35722,35725,35727,35729],{"class":3834,"line":3873},[3832,35723,35724],{"class":3853},"    timeout:",[3832,35726,11403],{"class":5726},[3832,35728,11662],{"class":3849},[3832,35730,35731],{"class":3838},"\u002F\u002F 10 секунд\n",[3832,35733,35734],{"class":3834,"line":3880},[3832,35735,4566],{"class":3849},[3801,35737,35738],{},[3770,35739,35740],{},"4. Retry логіка (для критичних запитів):",[3822,35742,35744],{"className":3824,"code":35743,"language":3826,"meta":3827,"style":3827},"getImportantData: builder.query({\n    query: () => '\u002Fimportant',\n    \u002F\u002F Повторити запит 3 рази з затримкою\n    extraOptions: { maxRetries: 3 },\n})\n",[3829,35745,35746,35761,35777,35782,35796],{"__ignoreMap":3827},[3832,35747,35748,35751,35753,35755,35757,35759],{"class":3834,"line":3835},[3832,35749,35750],{"class":5204},"getImportantData",[3832,35752,3906],{"class":3849},[3832,35754,4310],{"class":3853},[3832,35756,4183],{"class":3849},[3832,35758,6319],{"class":4117},[3832,35760,4267],{"class":3849},[3832,35762,35763,35766,35768,35770,35772,35775],{"class":3834,"line":3842},[3832,35764,35765],{"class":4117},"    query",[3832,35767,4304],{"class":3853},[3832,35769,4137],{"class":3849},[3832,35771,4140],{"class":3889},[3832,35773,35774],{"class":3869}," '\u002Fimportant'",[3832,35776,4072],{"class":3849},[3832,35778,35779],{"class":3834,"line":3873},[3832,35780,35781],{"class":3838},"    \u002F\u002F Повторити запит 3 рази з затримкою\n",[3832,35783,35784,35787,35789,35792,35794],{"class":3834,"line":3880},[3832,35785,35786],{"class":3853},"    extraOptions:",[3832,35788,3850],{"class":3849},[3832,35790,35791],{"class":3853},"maxRetries:",[3832,35793,10645],{"class":5726},[3832,35795,5145],{"class":3849},[3832,35797,35798],{"class":3834,"line":3886},[3832,35799,4566],{"class":3849},[35801,35802,35803],"style",{},"html pre.shiki code .spJ8K, html code.shiki .spJ8K{--shiki-light:#008000;--shiki-default:#6A9955;--shiki-dark:#6A9955}html pre.shiki code .s8xlr, html code.shiki .s8xlr{--shiki-light:#AF00DB;--shiki-default:#C586C0;--shiki-dark:#C586C0}html pre.shiki code .sHH4Y, html code.shiki .sHH4Y{--shiki-light:#000000;--shiki-default:#D4D4D4;--shiki-dark:#D4D4D4}html pre.shiki code .siwwj, html code.shiki .siwwj{--shiki-light:#001080;--shiki-default:#9CDCFE;--shiki-dark:#9CDCFE}html pre.shiki code .sbdoH, html code.shiki .sbdoH{--shiki-light:#A31515;--shiki-default:#CE9178;--shiki-dark:#CE9178}html pre.shiki code .su1O8, html code.shiki .su1O8{--shiki-light:#0000FF;--shiki-default:#569CD6;--shiki-dark:#569CD6}html pre.shiki code .sN1BT, html code.shiki .sN1BT{--shiki-light:#267F99;--shiki-default:#4EC9B0;--shiki-dark:#4EC9B0}html pre.shiki code .s-QsJ, html code.shiki .s-QsJ{--shiki-light:#0070C1;--shiki-default:#4FC1FF;--shiki-dark:#4FC1FF}html pre.shiki code .s8Opu, html code.shiki .s8Opu{--shiki-light:#795E26;--shiki-default:#DCDCAA;--shiki-dark:#DCDCAA}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s0P7L, html code.shiki .s0P7L{--shiki-light:#800000;--shiki-default:#808080;--shiki-dark:#808080}html pre.shiki code .sa4r_, html code.shiki .sa4r_{--shiki-light:#E50000;--shiki-default:#9CDCFE;--shiki-dark:#9CDCFE}html pre.shiki code .sD7JJ, html code.shiki .sD7JJ{--shiki-light:#000000FF;--shiki-default:#D4D4D4;--shiki-dark:#D4D4D4}html pre.shiki code .s5IvJ, html code.shiki .s5IvJ{--shiki-light:#000000;--shiki-default:#C8C8C8;--shiki-dark:#C8C8C8}html pre.shiki code .sJj4R, html code.shiki .sJj4R{--shiki-light:#098658;--shiki-default:#B5CEA8;--shiki-dark:#B5CEA8}html pre.shiki code .sLwNe, html code.shiki .sLwNe{--shiki-light:#0451A5;--shiki-default:#9CDCFE;--shiki-dark:#9CDCFE}html pre.shiki code .se1LK, html code.shiki .se1LK{--shiki-light:#CD3131;--shiki-default:#F44747;--shiki-dark:#F44747}html pre.shiki code .sjcCO, html code.shiki .sjcCO{--shiki-light:#EE0000;--shiki-default:#D7BA7D;--shiki-dark:#D7BA7D}",{"title":3827,"searchDepth":3842,"depth":3842,"links":35805},[35806,35817,35824,35840,35852,35866,35876,35887,35888,35890,35891,35900,35907,35908,35909,35910,35927,35928],{"id":3798,"depth":3842,"text":3799,"children":35807},[35808,35809,35810,35811,35812,35813,35814,35815,35816],{"id":3811,"depth":3873,"text":3812},{"id":5031,"depth":3873,"text":5032},{"id":5424,"depth":3873,"text":5425},{"id":5434,"depth":3873,"text":5435},{"id":5441,"depth":3873,"text":5442},{"id":5448,"depth":3873,"text":5449},{"id":5799,"depth":3873,"text":5800},{"id":6080,"depth":3873,"text":6081},{"id":6125,"depth":3873,"text":6126},{"id":6831,"depth":3842,"text":6832,"children":35818},[35819,35820,35821,35822,35823],{"id":6838,"depth":3873,"text":6839},{"id":7661,"depth":3873,"text":7662},{"id":8087,"depth":3873,"text":8088},{"id":8291,"depth":3873,"text":8292},{"id":8602,"depth":3873,"text":8603},{"id":9091,"depth":3842,"text":35825,"children":35826},"Перші кроки: Налаштування createApi",[35827,35828,35829,35830,35831,35832,35833,35834,35835,35836,35838],{"id":9100,"depth":3873,"text":9101},{"id":9179,"depth":3873,"text":9180},{"id":9480,"depth":3873,"text":9481},{"id":9819,"depth":3873,"text":9820},{"id":10762,"depth":3873,"text":10763},{"id":10773,"depth":3873,"text":10774},{"id":10780,"depth":3873,"text":10781},{"id":10793,"depth":3873,"text":10794},{"id":10807,"depth":3873,"text":942},{"id":10816,"depth":3873,"text":35837},"Розуміння архітектури: що генерує createApi",{"id":11006,"depth":3873,"text":35839},"Поглиблене налаштування: Параметри createApi",{"id":12283,"depth":3842,"text":12284,"children":35841},[35842,35843,35844,35845,35846,35847,35848,35849,35850,35851],{"id":12290,"depth":3873,"text":12291},{"id":12979,"depth":3873,"text":12980},{"id":12989,"depth":3873,"text":12990},{"id":12996,"depth":3873,"text":12997},{"id":13003,"depth":3873,"text":13004},{"id":13015,"depth":3873,"text":13016},{"id":13089,"depth":3873,"text":13090},{"id":13436,"depth":3873,"text":13437},{"id":14295,"depth":3873,"text":14296},{"id":14420,"depth":3873,"text":14421},{"id":15511,"depth":3842,"text":15512,"children":35853},[35854,35855,35856,35857,35858,35859,35860,35861,35862,35863,35864],{"id":15522,"depth":3873,"text":15523},{"id":15892,"depth":3873,"text":15893},{"id":16243,"depth":3873,"text":16244},{"id":16253,"depth":3873,"text":16254},{"id":16263,"depth":3873,"text":16264},{"id":16272,"depth":3873,"text":16273},{"id":16296,"depth":3873,"text":16297},{"id":17270,"depth":3873,"text":17271},{"id":17877,"depth":3873,"text":17878},{"id":19096,"depth":3873,"text":19097},{"id":19502,"depth":3873,"text":35865},"Рівень 6: Оптимізація рендерів через selectFromResult",{"id":19782,"depth":3842,"text":19783,"children":35867},[35868,35869,35870,35871,35872,35873,35874,35875],{"id":19801,"depth":3873,"text":19802},{"id":19900,"depth":3873,"text":19901},{"id":21118,"depth":3873,"text":21119},{"id":21686,"depth":3873,"text":21687},{"id":22239,"depth":3873,"text":22240},{"id":22831,"depth":3873,"text":22832},{"id":23486,"depth":3873,"text":23487},{"id":23753,"depth":3873,"text":23754},{"id":24148,"depth":3842,"text":24149,"children":35877},[35878,35879,35880,35881,35882,35883,35884,35885,35886],{"id":24160,"depth":3873,"text":24161},{"id":24414,"depth":3873,"text":24415},{"id":24778,"depth":3873,"text":24779},{"id":25177,"depth":3873,"text":25178},{"id":26315,"depth":3873,"text":26316},{"id":26517,"depth":3873,"text":26518},{"id":27135,"depth":3873,"text":27136},{"id":27233,"depth":3873,"text":27234},{"id":27564,"depth":3873,"text":27565},{"id":27832,"depth":3842,"text":27833},{"id":28292,"depth":3842,"text":35889},"Realtime-оновлення: WebSockets через onCacheEntryAdded",{"id":28687,"depth":3842,"text":28688},{"id":29149,"depth":3842,"text":29150,"children":35892},[35893,35894,35895,35897,35898],{"id":29156,"depth":3873,"text":29157},{"id":29191,"depth":3873,"text":29192},{"id":29197,"depth":3873,"text":35896},"Крок 1. Створення сервісу notesApi.ts",{"id":29764,"depth":3873,"text":29765},{"id":29915,"depth":3873,"text":35899},"Крок 3. Екран керування нотатками NotesScreen.tsx",{"id":31056,"depth":3842,"text":31057,"children":35901},[35902,35904,35905],{"id":31072,"depth":3873,"text":35903},"1. Повний сервіс src\u002Fservices\u002FtripsApi.ts",{"id":31833,"depth":3873,"text":31834},{"id":32027,"depth":3873,"text":35906},"3. Оновлення головного екрана app\u002F(tabs)\u002Ftrips\u002Findex.tsx",{"id":32845,"depth":3842,"text":32846},{"id":32892,"depth":3842,"text":32893},{"id":32975,"depth":3842,"text":32976},{"id":33025,"depth":3842,"text":33026,"children":35911},[35912,35913,35914,35915,35916,35917,35918,35919,35920,35921,35922,35923,35924,35925,35926],{"id":33032,"depth":3873,"text":33033},{"id":33747,"depth":3873,"text":33748},{"id":33754,"depth":3873,"text":33755},{"id":33761,"depth":3873,"text":33762},{"id":33811,"depth":3873,"text":33812},{"id":34531,"depth":3873,"text":34532},{"id":34541,"depth":3873,"text":34542},{"id":34554,"depth":3873,"text":34555},{"id":34567,"depth":3873,"text":34568},{"id":34576,"depth":3873,"text":34577},{"id":35127,"depth":3873,"text":10763},{"id":35137,"depth":3873,"text":35138},{"id":35147,"depth":3873,"text":35148},{"id":35154,"depth":3873,"text":35155},{"id":35161,"depth":3873,"text":35162},{"id":35173,"depth":3842,"text":35174},{"id":35277,"depth":3842,"text":32976},"Практичний навчальний посібник з RTK Query у React Native — від простих прикладів до складних сценаріїв. Дізнайтеся як автоматизувати роботу з серверними даними, налаштувати кеш, інвалідацію та оптимістичні оновлення у мобільному застосунку.","md",null,{},{"title":3452,"description":35929},"YSvu2K8HeHW0mpmcJl1VeBEbp7hUdgt8NPWTvIPH8GA",[35936,35938],{"title":3448,"path":3449,"stem":3450,"description":35937,"children":-1},"Повний практичний посібник з Redux Toolkit у React Native — будова Store, Slice, Reducer, Action, createListenerMiddleware, персистентність з MMKV, оптимістичні оновлення, скасування thunk через AbortController, createEntityAdapter, Reselect мемоїзація та тестування логіки.",{"title":3456,"path":3457,"stem":3458,"description":35939,"children":-1},"Практичний розбір механізмів автентифікації, управління сесіями, SecureStore та захищених маршрутів у React Native",1788069965237]