| <!DOCTYPE html><html class="default" lang="en" data-base=".."><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>docs/guides/routing | react-declarative</title><meta name="description" content="Documentation for react-declarative"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script><script async src="../assets/hierarchy.js" id="tsd-hierarchy-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><div class="table-cell" id="tsd-search"><div class="field"><label for="tsd-search-field" class="tsd-widget tsd-toolbar-icon search no-caption"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></label><input type="text" id="tsd-search-field" aria-label="Search"/></div><div class="field"><div id="tsd-toolbar-links"></div></div><ul class="results"><li class="state loading">Preparing search index...</li><li class="state failure">The search index is not available</li></ul><a href="../index.html" class="title">react-declarative</a></div><div class="table-cell" id="tsd-widgets"><a href="#" class="tsd-widget tsd-toolbar-icon menu no-caption" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb"><li><a href="../modules.html">react-declarative</a></li><li><a href="docs_guides_routing.html">docs/guides/routing</a></li></ul></div><div class="tsd-panel tsd-typography"><a id="client-side-routing-with-the-switch-component" class="tsd-anchor"></a><h1 class="tsd-anchor-link">Client-side routing with the Switch component<a href="#client-side-routing-with-the-switch-component" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h1><p>React-declarative ships its own router centered on the <code><Switch /></code> component. You describe your application's routes as a plain array of <code>ISwitchItem</code> objects — each one carrying the path pattern, the component to render, optional async guards, prefetch logic, and redirect rules. <code><Switch /></code> reads the current URL from a <code>history</code> object and renders the matching element, running guards and prefetches before the component mounts.</p> |
| <a id="defining-routes" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Defining routes<a href="#defining-routes" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p>Each route in the <code>items</code> array is an <code>ISwitchItem</code>. The minimum required field is <code>path</code>.</p> |
| <pre><code class="tsx"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">Switch</span><span class="hl-1">, </span><span class="hl-2">ISwitchItem</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">'react-declarative'</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">createBrowserHistory</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">'history'</span><span class="hl-1">;</span><br/><br/><span class="hl-0">import</span><span class="hl-1"> </span><span class="hl-2">HomePage</span><span class="hl-1"> </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">'./pages/HomePage'</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> </span><span class="hl-2">ProfilePage</span><span class="hl-1"> </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">'./pages/ProfilePage'</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> </span><span class="hl-2">LoginPage</span><span class="hl-1"> </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">'./pages/LoginPage'</span><span class="hl-1">;</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-10">history</span><span class="hl-1"> = </span><span class="hl-5">createBrowserHistory</span><span class="hl-1">();</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-10">routes</span><span class="hl-1">: </span><span class="hl-7">ISwitchItem</span><span class="hl-1">[] = [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">path:</span><span class="hl-1"> </span><span class="hl-3">'/'</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">redirect:</span><span class="hl-1"> </span><span class="hl-3">'/profile'</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">path:</span><span class="hl-1"> </span><span class="hl-3">'/profile'</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">element</span><span class="hl-2">:</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-6"><</span><span class="hl-7">ProfilePage</span><span class="hl-1"> </span><span class="hl-6">/></span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">path:</span><span class="hl-1"> </span><span class="hl-3">'/login'</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">element</span><span class="hl-2">:</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-6"><</span><span class="hl-7">LoginPage</span><span class="hl-1"> </span><span class="hl-6">/></span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1">];</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-5">App</span><span class="hl-1"> = () </span><span class="hl-4">=></span><span class="hl-1"> (</span><br/><span class="hl-1"> </span><span class="hl-6"><</span><span class="hl-7">Switch</span><br/><span class="hl-1"> </span><span class="hl-8">history</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">history</span><span class="hl-4">}</span><br/><span class="hl-1"> </span><span class="hl-8">items</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">routes</span><span class="hl-4">}</span><br/><span class="hl-1"> </span><span class="hl-8">Loader</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-9">() </span><span class="hl-4">=></span><span class="hl-9"> </span><span class="hl-6"><</span><span class="hl-18">p</span><span class="hl-6">></span><span class="hl-9">Loading...</span><span class="hl-6"></</span><span class="hl-18">p</span><span class="hl-6">></span><span class="hl-4">}</span><br/><span class="hl-1"> </span><span class="hl-8">NotFound</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-9">() </span><span class="hl-4">=></span><span class="hl-9"> </span><span class="hl-6"><</span><span class="hl-18">p</span><span class="hl-6">></span><span class="hl-9">Page not found</span><span class="hl-6"></</span><span class="hl-18">p</span><span class="hl-6">></span><span class="hl-4">}</span><br/><span class="hl-1"> </span><span class="hl-6">/></span><br/><span class="hl-1">);</span> |
| </code><button type="button">Copy</button></pre> |
|
|
| <blockquote> |
| <p><strong>Note:</strong> Pass <code>element</code> as a factory function <code>() => <MyPage /></code>, not as a component |
| reference <code>MyPage</code>. This ensures the component is only instantiated when the |
| route matches, enabling code-splitting patterns.</p> |
| </blockquote> |
| <a id="guards--async-authentication-checks" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Guards — async authentication checks<a href="#guards--async-authentication-checks" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p>The <code>guard</code> function runs before the element renders. If it returns <code>false</code>, the route is blocked (typically you redirect to a login page from inside the guard). Guards can be async, making them suitable for API-based permission checks.</p> |
| <pre><code class="tsx"><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-10">routes</span><span class="hl-1">: </span><span class="hl-7">ISwitchItem</span><span class="hl-1">[] = [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">path:</span><span class="hl-1"> </span><span class="hl-3">'/mint-page'</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">guard</span><span class="hl-2">:</span><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-2">ioc</span><span class="hl-1">.</span><span class="hl-2">roleService</span><span class="hl-1">.</span><span class="hl-5">has</span><span class="hl-1">(</span><span class="hl-3">'whitelist'</span><span class="hl-1">),</span><br/><span class="hl-1"> </span><span class="hl-5">element</span><span class="hl-2">:</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-6"><</span><span class="hl-7">MintPage</span><span class="hl-1"> </span><span class="hl-6">/></span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">path:</span><span class="hl-1"> </span><span class="hl-3">'/admin'</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">guard</span><span class="hl-2">:</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-2">ioc</span><span class="hl-1">.</span><span class="hl-2">authService</span><span class="hl-1">.</span><span class="hl-5">hasRole</span><span class="hl-1">(</span><span class="hl-3">'admin'</span><span class="hl-1">),</span><br/><span class="hl-1"> </span><span class="hl-5">element</span><span class="hl-2">:</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-6"><</span><span class="hl-7">AdminPage</span><span class="hl-1"> </span><span class="hl-6">/></span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1">];</span> |
| </code><button type="button">Copy</button></pre> |
|
|
| <blockquote> |
| <p><strong>Warning:</strong> If <code>guard</code> returns <code>false</code>, the route simply does not render — it does not |
| automatically redirect. Add a separate redirect route or handle navigation |
| inside your <code>guard</code> function if you want to send unauthenticated users to a |
| login page.</p> |
| </blockquote> |
| <a id="prefetch-and-unload-lifecycle-hooks" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Prefetch and unload lifecycle hooks<a href="#prefetch-and-unload-lifecycle-hooks" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p><code>prefetch</code> runs once before the element mounts. Use it to initialize services (connect to a wallet, fetch required config) that the page depends on. <code>unload</code> is the corresponding cleanup hook that runs when the route is left.</p> |
| <pre><code class="tsx"><span class="hl-1">{</span><br/><span class="hl-1"> </span><span class="hl-20">path</span><span class="hl-1">: </span><span class="hl-3">'/mint-page'</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-20">guard</span><span class="hl-1">: </span><span class="hl-4">async</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-2">ioc</span><span class="hl-1">.</span><span class="hl-2">roleService</span><span class="hl-1">.</span><span class="hl-5">has</span><span class="hl-1">(</span><span class="hl-3">'whitelist'</span><span class="hl-1">),</span><br/><span class="hl-1"> </span><span class="hl-20">prefetch</span><span class="hl-1">: </span><span class="hl-4">async</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-2">ioc</span><span class="hl-1">.</span><span class="hl-2">ethersService</span><span class="hl-1">.</span><span class="hl-5">init</span><span class="hl-1">(),</span><br/><span class="hl-1"> </span><span class="hl-20">unload</span><span class="hl-1">: </span><span class="hl-4">async</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-2">ioc</span><span class="hl-1">.</span><span class="hl-2">ethersService</span><span class="hl-1">.</span><span class="hl-5">dispose</span><span class="hl-1">(),</span><br/><span class="hl-1"> </span><span class="hl-20">element</span><span class="hl-1">: () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-6"><</span><span class="hl-7">MintPage</span><span class="hl-1"> </span><span class="hl-6">/></span><span class="hl-1">,</span><br/><span class="hl-1">}</span> |
| </code><button type="button">Copy</button></pre> |
|
|
| <a id="redirects" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Redirects<a href="#redirects" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p><code>redirect</code> accepts either a string path or a function. The function receives the current route params and can return a path string or <code>null</code> (no redirect).</p> |
| <pre><code class="tsx"><span class="hl-17">// Static redirect</span><br/><span class="hl-1">{</span><br/><span class="hl-1"> </span><span class="hl-20">path</span><span class="hl-1">: </span><span class="hl-3">'/'</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-20">redirect</span><span class="hl-1">: </span><span class="hl-3">'/profile'</span><span class="hl-1">,</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-17">// Conditional redirect — send to login if not authenticated</span><br/><span class="hl-1">{</span><br/><span class="hl-1"> </span><span class="hl-20">path</span><span class="hl-1">: </span><span class="hl-3">'/'</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-20">redirect</span><span class="hl-1">: () </span><span class="hl-4">=></span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">ioc</span><span class="hl-1">.</span><span class="hl-2">authService</span><span class="hl-1">.</span><span class="hl-2">isAuthorized</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> </span><span class="hl-3">'/profile'</span><span class="hl-1">;</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> </span><span class="hl-3">'/login'</span><span class="hl-1">;</span><br/><span class="hl-1"> },</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-17">// Redirect with route params</span><br/><span class="hl-1">{</span><br/><span class="hl-1"> </span><span class="hl-20">path</span><span class="hl-1">: </span><span class="hl-3">'/ticket/:id'</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-20">redirect</span><span class="hl-1">: ({ </span><span class="hl-2">id</span><span class="hl-1"> }) </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-3">`/ticket/</span><span class="hl-4">${</span><span class="hl-2">id</span><span class="hl-4">}</span><span class="hl-3">/card`</span><span class="hl-1">,</span><br/><span class="hl-1">}</span> |
| </code><button type="button">Copy</button></pre> |
|
|
| <a id="full-example-with-guards-and-feature-based-access" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Full example with guards and feature-based access<a href="#full-example-with-guards-and-feature-based-access" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p>The following example mirrors the pattern used in real CRM applications:</p> |
| <pre><code class="tsx"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">Switch</span><span class="hl-1">, </span><span class="hl-2">ISwitchItem</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">'react-declarative'</span><span class="hl-1">;</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-10">routes</span><span class="hl-1">: </span><span class="hl-7">ISwitchItem</span><span class="hl-1">[] = [</span><br/><span class="hl-1"> </span><span class="hl-17">// Root redirect based on auth state</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">path:</span><span class="hl-1"> </span><span class="hl-3">'/'</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">redirect</span><span class="hl-2">:</span><span class="hl-1"> () </span><span class="hl-4">=></span><br/><span class="hl-1"> </span><span class="hl-2">ioc</span><span class="hl-1">.</span><span class="hl-2">authService</span><span class="hl-1">.</span><span class="hl-2">isAuthorized</span><span class="hl-1"> ? </span><span class="hl-3">'/dashboard'</span><span class="hl-1"> : </span><span class="hl-3">'/login'</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><br/><span class="hl-1"> </span><span class="hl-17">// Public routes</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">path:</span><span class="hl-1"> </span><span class="hl-3">'/login'</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">element</span><span class="hl-2">:</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-6"><</span><span class="hl-7">LoginPage</span><span class="hl-1"> </span><span class="hl-6">/></span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><br/><span class="hl-1"> </span><span class="hl-17">// Feature-gated routes</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">path:</span><span class="hl-1"> </span><span class="hl-3">'/dashboard'</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">guard</span><span class="hl-2">:</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-2">ioc</span><span class="hl-1">.</span><span class="hl-2">authService</span><span class="hl-1">.</span><span class="hl-5">hasFeature</span><span class="hl-1">(</span><span class="hl-3">'dashboard_read'</span><span class="hl-1">),</span><br/><span class="hl-1"> </span><span class="hl-5">element</span><span class="hl-2">:</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-6"><</span><span class="hl-7">DashboardPage</span><span class="hl-1"> </span><span class="hl-6">/></span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">path:</span><span class="hl-1"> </span><span class="hl-3">'/users'</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">guard</span><span class="hl-2">:</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-2">ioc</span><span class="hl-1">.</span><span class="hl-2">authService</span><span class="hl-1">.</span><span class="hl-5">hasRole</span><span class="hl-1">(</span><span class="hl-3">'admin'</span><span class="hl-1">),</span><br/><span class="hl-1"> </span><span class="hl-5">element</span><span class="hl-2">:</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-6"><</span><span class="hl-7">UserListPage</span><span class="hl-1"> </span><span class="hl-6">/></span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">path:</span><span class="hl-1"> </span><span class="hl-3">'/users/:id/card'</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">guard</span><span class="hl-2">:</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-2">ioc</span><span class="hl-1">.</span><span class="hl-2">authService</span><span class="hl-1">.</span><span class="hl-5">hasRole</span><span class="hl-1">(</span><span class="hl-3">'admin'</span><span class="hl-1">),</span><br/><span class="hl-1"> </span><span class="hl-5">element</span><span class="hl-2">:</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-6"><</span><span class="hl-7">UserDetailPage</span><span class="hl-1"> </span><span class="hl-6">/></span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><br/><span class="hl-1"> </span><span class="hl-17">// Redirect /users/:id to the card sub-route</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">path:</span><span class="hl-1"> </span><span class="hl-3">'/users/:id'</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">redirect</span><span class="hl-2">:</span><span class="hl-1"> ({ </span><span class="hl-2">id</span><span class="hl-1"> }) </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-3">`/users/</span><span class="hl-4">${</span><span class="hl-2">id</span><span class="hl-4">}</span><span class="hl-3">/card`</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><br/><span class="hl-1"> </span><span class="hl-17">// Route with prefetch/unload</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">path:</span><span class="hl-1"> </span><span class="hl-3">'/mint'</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">guard</span><span class="hl-2">:</span><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-2">ioc</span><span class="hl-1">.</span><span class="hl-2">roleService</span><span class="hl-1">.</span><span class="hl-5">has</span><span class="hl-1">(</span><span class="hl-3">'whitelist'</span><span class="hl-1">),</span><br/><span class="hl-1"> </span><span class="hl-5">prefetch</span><span class="hl-2">:</span><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-2">ioc</span><span class="hl-1">.</span><span class="hl-2">ethersService</span><span class="hl-1">.</span><span class="hl-5">init</span><span class="hl-1">(),</span><br/><span class="hl-1"> </span><span class="hl-5">unload</span><span class="hl-2">:</span><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-2">ioc</span><span class="hl-1">.</span><span class="hl-2">ethersService</span><span class="hl-1">.</span><span class="hl-5">dispose</span><span class="hl-1">(),</span><br/><span class="hl-1"> </span><span class="hl-5">redirect</span><span class="hl-2">:</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> { </span><span class="hl-10">isMetamaskAvailable</span><span class="hl-1">, </span><span class="hl-10">isProviderConnected</span><span class="hl-1"> } = </span><span class="hl-2">ioc</span><span class="hl-1">.</span><span class="hl-2">ethersService</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (!</span><span class="hl-2">isMetamaskAvailable</span><span class="hl-1"> || !</span><span class="hl-2">isProviderConnected</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> </span><span class="hl-3">'/connect'</span><span class="hl-1">;</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> </span><span class="hl-4">null</span><span class="hl-1">;</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-5">element</span><span class="hl-2">:</span><span class="hl-1"> () </span><span class="hl-4">=></span><span class="hl-1"> </span><span class="hl-6"><</span><span class="hl-7">MintPage</span><span class="hl-1"> </span><span class="hl-6">/></span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1">];</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-5">App</span><span class="hl-1"> = () </span><span class="hl-4">=></span><span class="hl-1"> (</span><br/><span class="hl-1"> </span><span class="hl-6"><</span><span class="hl-7">Switch</span><br/><span class="hl-1"> </span><span class="hl-8">history</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">history</span><span class="hl-4">}</span><br/><span class="hl-1"> </span><span class="hl-8">items</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">routes</span><span class="hl-4">}</span><br/><span class="hl-1"> </span><span class="hl-8">Loader</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-9">() </span><span class="hl-4">=></span><span class="hl-9"> </span><span class="hl-6"><</span><span class="hl-7">CircularProgress</span><span class="hl-9"> </span><span class="hl-6">/></span><span class="hl-4">}</span><br/><span class="hl-1"> </span><span class="hl-8">NotFound</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-9">() </span><span class="hl-4">=></span><span class="hl-9"> </span><span class="hl-6"><</span><span class="hl-7">NotFoundPage</span><span class="hl-9"> </span><span class="hl-6">/></span><span class="hl-4">}</span><br/><span class="hl-1"> </span><span class="hl-6">/></span><br/><span class="hl-1">);</span> |
| </code><button type="button">Copy</button></pre> |
|
|
| <a id="route-parameter-hooks" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Route parameter hooks<a href="#route-parameter-hooks" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><a id="userouteparams" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><code>useRouteParams</code><a href="#userouteparams" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p><code>useRouteParams</code> subscribes to history changes and returns the extracted URL parameters for whichever route is currently active.</p> |
| <pre><code class="tsx"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">useRouteParams</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">'react-declarative'</span><span class="hl-1">;</span><br/><br/><span class="hl-4">interface</span><span class="hl-1"> </span><span class="hl-7">IParams</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">id</span><span class="hl-1">: </span><span class="hl-7">string</span><span class="hl-1">;</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-5">UserDetailPage</span><span class="hl-1"> = () </span><span class="hl-4">=></span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-10">params</span><span class="hl-1"> = </span><span class="hl-5">useRouteParams</span><span class="hl-1"><</span><span class="hl-7">IParams</span><span class="hl-1">>(</span><span class="hl-2">routes</span><span class="hl-1">, </span><span class="hl-2">history</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-17">// params.id === '42' when URL is /users/42/card</span><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> </span><span class="hl-6"><</span><span class="hl-18">div</span><span class="hl-6">></span><span class="hl-1">User ID: </span><span class="hl-4">{</span><span class="hl-2">params</span><span class="hl-9">?.</span><span class="hl-2">id</span><span class="hl-4">}</span><span class="hl-6"></</span><span class="hl-18">div</span><span class="hl-6">></span><span class="hl-1">;</span><br/><span class="hl-1">};</span> |
| </code><button type="button">Copy</button></pre> |
|
|
| <a id="userouteitem" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><code>useRouteItem</code><a href="#userouteitem" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p><code>useRouteItem</code> returns the matching <code>ISwitchItem</code> object from your routes array (not just its params). Use this to access custom properties you have added to your route definitions.</p> |
| <pre><code class="tsx"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">useRouteItem</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">'react-declarative'</span><span class="hl-1">;</span><br/><br/><span class="hl-4">interface</span><span class="hl-1"> </span><span class="hl-7">IAppRoute</span><span class="hl-1"> </span><span class="hl-4">extends</span><span class="hl-1"> </span><span class="hl-7">ISwitchItem</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">sideMenu</span><span class="hl-1">?: </span><span class="hl-7">string</span><span class="hl-1">;</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-5">Sidebar</span><span class="hl-1"> = () </span><span class="hl-4">=></span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-10">currentRoute</span><span class="hl-1"> = </span><span class="hl-5">useRouteItem</span><span class="hl-1"><</span><span class="hl-7">IAppRoute</span><span class="hl-1">>(</span><span class="hl-2">routes</span><span class="hl-1">, </span><span class="hl-2">history</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-17">// currentRoute.sideMenu === 'root.report.ticket' when on /ticket route</span><br/><span class="hl-1">};</span> |
| </code><button type="button">Copy</button></pre> |
|
|
| <a id="utility-functions" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Utility functions<a href="#utility-functions" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p><code>getRouteParams</code> and <code>getRouteItem</code> are the synchronous, non-hook equivalents. Use them outside React components — for example, inside service classes or event handlers.</p> |
| <pre><code class="tsx"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">getRouteParams</span><span class="hl-1">, </span><span class="hl-2">getRouteItem</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">'react-declarative'</span><span class="hl-1">;</span><br/><br/><span class="hl-17">// In a service or event handler:</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-10">params</span><span class="hl-1"> = </span><span class="hl-5">getRouteParams</span><span class="hl-1">(</span><span class="hl-2">routes</span><span class="hl-1">, </span><span class="hl-2">window</span><span class="hl-1">.</span><span class="hl-2">location</span><span class="hl-1">.</span><span class="hl-2">pathname</span><span class="hl-1">);</span><br/><span class="hl-17">// { id: '42' }</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-10">matchedRoute</span><span class="hl-1"> = </span><span class="hl-5">getRouteItem</span><span class="hl-1">(</span><span class="hl-2">routes</span><span class="hl-1">, </span><span class="hl-2">window</span><span class="hl-1">.</span><span class="hl-2">location</span><span class="hl-1">.</span><span class="hl-2">pathname</span><span class="hl-1">);</span><br/><span class="hl-17">// The ISwitchItem that matched</span> |
| </code><button type="button">Copy</button></pre> |
|
|
| <p><code>parseRouteUrl</code> checks whether a pathname matches a given path pattern and returns the extracted params or <code>null</code>:</p> |
| <pre><code class="tsx"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">parseRouteUrl</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">'react-declarative'</span><span class="hl-1">;</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-10">params</span><span class="hl-1"> = </span><span class="hl-5">parseRouteUrl</span><span class="hl-1">(</span><span class="hl-3">'/ticket/:id/card'</span><span class="hl-1">, </span><span class="hl-3">'/ticket/42/card'</span><span class="hl-1">);</span><br/><span class="hl-17">// { id: '42' }</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-10">noMatch</span><span class="hl-1"> = </span><span class="hl-5">parseRouteUrl</span><span class="hl-1">(</span><span class="hl-3">'/ticket/:id/card'</span><span class="hl-1">, </span><span class="hl-3">'/dashboard'</span><span class="hl-1">);</span><br/><span class="hl-17">// null</span> |
| </code><button type="button">Copy</button></pre> |
|
|
| <a id="nested-routing-with-outletview" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Nested routing with <code>OutletView</code><a href="#nested-routing-with-outletview" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p>For views that contain their own sub-navigation (a detail page with tabs for "Data", "Files", "Settings"), use <code>OutletView</code>. It renders one sub-route at a time and handles transitions between them.</p> |
| <pre><code class="tsx"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">OutletView</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">'react-declarative'</span><span class="hl-1">;</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-5">UserDetailPage</span><span class="hl-1"> = ({ </span><span class="hl-2">history</span><span class="hl-1"> }) </span><span class="hl-4">=></span><span class="hl-1"> (</span><br/><span class="hl-1"> </span><span class="hl-6"><</span><span class="hl-7">OutletView</span><br/><span class="hl-1"> </span><span class="hl-8">history</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">history</span><span class="hl-4">}</span><br/><span class="hl-1"> </span><span class="hl-8">routes</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-9">[</span><br/><span class="hl-9"> {</span><br/><span class="hl-9"> </span><span class="hl-2">id:</span><span class="hl-9"> </span><span class="hl-3">'card'</span><span class="hl-9">,</span><br/><span class="hl-9"> </span><span class="hl-5">isActive</span><span class="hl-2">:</span><span class="hl-9"> (</span><span class="hl-2">pathname</span><span class="hl-9">) </span><span class="hl-4">=></span><span class="hl-9"> </span><span class="hl-1">!!</span><span class="hl-5">parseRouteUrl</span><span class="hl-9">(</span><span class="hl-3">'/users/:id/card'</span><span class="hl-9">, </span><span class="hl-2">pathname</span><span class="hl-9">),</span><br/><span class="hl-9"> </span><span class="hl-2">element:</span><span class="hl-9"> </span><span class="hl-2">UserCardView</span><span class="hl-9">,</span><br/><span class="hl-9"> },</span><br/><span class="hl-9"> {</span><br/><span class="hl-9"> </span><span class="hl-2">id:</span><span class="hl-9"> </span><span class="hl-3">'files'</span><span class="hl-9">,</span><br/><span class="hl-9"> </span><span class="hl-5">isActive</span><span class="hl-2">:</span><span class="hl-9"> (</span><span class="hl-2">pathname</span><span class="hl-9">) </span><span class="hl-4">=></span><span class="hl-9"> </span><span class="hl-1">!!</span><span class="hl-5">parseRouteUrl</span><span class="hl-9">(</span><span class="hl-3">'/users/:id/files'</span><span class="hl-9">, </span><span class="hl-2">pathname</span><span class="hl-9">),</span><br/><span class="hl-9"> </span><span class="hl-2">element:</span><span class="hl-9"> </span><span class="hl-2">UserFilesView</span><span class="hl-9">,</span><br/><span class="hl-9"> },</span><br/><span class="hl-9"> ]</span><span class="hl-4">}</span><br/><span class="hl-1"> </span><span class="hl-6">/></span><br/><span class="hl-1">);</span> |
| </code><button type="button">Copy</button></pre> |
|
|
| <p>Navigate between outlets with <code>history.replace</code>:</p> |
| <pre><code class="tsx"><span class="hl-2">history</span><span class="hl-1">.</span><span class="hl-5">replace</span><span class="hl-1">(</span><span class="hl-3">`/users/</span><span class="hl-4">${</span><span class="hl-2">id</span><span class="hl-4">}</span><span class="hl-3">/files`</span><span class="hl-1">);</span> |
| </code><button type="button">Copy</button></pre> |
|
|
| <a id="works-alongside-react-router" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Works alongside react-router<a href="#works-alongside-react-router" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p><code><Switch /></code> is not tied to react-router. It works with any <code>history</code> object from the <a href="https://www.npmjs.com/package/history"><code>history</code></a> package — <code>createBrowserHistory</code>, <code>createHashHistory</code>, or <code>createMemoryHistory</code>. If your application already uses react-router, you can use <code><Switch /></code> in a section of the app that does not need react-router's features, or replace react-router entirely.</p> |
| <blockquote> |
| <p><strong>Tip:</strong> The demo application in the library source (<code>demo/src/App.tsx</code>) uses |
| <code><Switch /></code> alongside <code><Scaffold /></code> to build a full navigation shell. It is |
| a good reference for how guards, redirects, and the history object fit |
| together.</p> |
| </blockquote> |
| </div></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div><details open class="tsd-accordion tsd-page-navigation"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>On This Page</h3></summary><div class="tsd-accordion-details"><a href="#client-side-routing-with-the-switch-component"><span>Client-<wbr/>side routing with the <wbr/>Switch component</span></a><ul><li><a href="#defining-routes"><span>Defining routes</span></a></li><li><a href="#guards--async-authentication-checks"><span>Guards — async authentication checks</span></a></li><li><a href="#prefetch-and-unload-lifecycle-hooks"><span>Prefetch and unload lifecycle hooks</span></a></li><li><a href="#redirects"><span>Redirects</span></a></li><li><a href="#full-example-with-guards-and-feature-based-access"><span>Full example with guards and feature-<wbr/>based access</span></a></li><li><a href="#route-parameter-hooks"><span>Route parameter hooks</span></a></li><li><ul><li><a href="#userouteparams"><span>use<wbr/>Route<wbr/>Params</span></a></li><li><a href="#userouteitem"><span>use<wbr/>Route<wbr/>Item</span></a></li></ul></li><li><a href="#utility-functions"><span>Utility functions</span></a></li><li><a href="#nested-routing-with-outletview"><span>Nested routing with <wbr/>Outlet<wbr/>View</span></a></li><li><a href="#works-alongside-react-router"><span>Works alongside react-<wbr/>router</span></a></li></ul></div></details></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">react-declarative</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html> |
|
|