reactive-route 0.0.1-alpha.26 → 0.0.1-alpha.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/LICENSE +1 -1
  2. package/dist/cjs/adapters/vue/index.js +39 -0
  3. package/dist/cjs/adapters/vue/package.json +1 -0
  4. package/dist/cjs/vue/index.js +0 -0
  5. package/dist/cjs/vue/package.json +1 -0
  6. package/dist/esm/adapters/vue/index.js +18 -0
  7. package/dist/esm/adapters/vue/package.json +1 -0
  8. package/dist/esm/vue/index.js +0 -0
  9. package/dist/esm/vue/package.json +1 -0
  10. package/dist/tsconfig.types.react.tsbuildinfo +1 -1
  11. package/dist/vue/index.d.ts +1 -1
  12. package/dist/vue/index.d.ts.map +1 -1
  13. package/e2e/app.test.ts +130 -0
  14. package/e2e/teardown.ts +12 -0
  15. package/package.json +25 -9
  16. package/playwright.config.ts +54 -0
  17. package/vitepress/.vitepress/cache/deps/_metadata.json +52 -0
  18. package/vitepress/.vitepress/cache/deps/chunk-FL23S3EK.js +12705 -0
  19. package/vitepress/.vitepress/cache/deps/chunk-FL23S3EK.js.map +7 -0
  20. package/vitepress/.vitepress/cache/deps/chunk-VGAXUAUJ.js +9952 -0
  21. package/vitepress/.vitepress/cache/deps/chunk-VGAXUAUJ.js.map +7 -0
  22. package/vitepress/.vitepress/cache/deps/package.json +3 -0
  23. package/vitepress/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +3844 -0
  24. package/vitepress/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +7 -0
  25. package/vitepress/.vitepress/cache/deps/vitepress___@vueuse_core.js +588 -0
  26. package/vitepress/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +7 -0
  27. package/vitepress/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js +1153 -0
  28. package/vitepress/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js.map +7 -0
  29. package/vitepress/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js +1665 -0
  30. package/vitepress/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js.map +7 -0
  31. package/vitepress/.vitepress/cache/deps/vitepress___minisearch.js +1812 -0
  32. package/vitepress/.vitepress/cache/deps/vitepress___minisearch.js.map +7 -0
  33. package/vitepress/.vitepress/cache/deps/vue.js +342 -0
  34. package/vitepress/.vitepress/cache/deps/vue.js.map +7 -0
  35. package/vitepress/.vitepress/config.mts +72 -0
  36. package/vitepress/.vitepress/theme/custom.css +9 -0
  37. package/vitepress/.vitepress/theme/index.ts +5 -0
  38. package/vitepress/examples/preact.md +22 -0
  39. package/vitepress/examples/react.md +22 -0
  40. package/vitepress/examples/solid.md +21 -0
  41. package/vitepress/file.svg +79 -0
  42. package/vitepress/guide/advanced.md +131 -0
  43. package/vitepress/guide/getting-started.md +139 -0
  44. package/vitepress/guide/index.md +44 -0
  45. package/vitepress/guide/preact.md +33 -0
  46. package/vitepress/guide/react.md +33 -0
  47. package/vitepress/guide/router-component.md +67 -0
  48. package/vitepress/guide/router-configuration.md +185 -0
  49. package/vitepress/guide/routes-configuration.md +191 -0
  50. package/vitepress/guide/solid.md +68 -0
  51. package/vitepress/guide/ssr.md +70 -0
  52. package/vitepress/index.md +29 -0
  53. package/vitest.vue.config.mjs +23 -0
  54. package/dist/vue/Router.d.ts +0 -4
  55. package/dist/vue/Router.d.ts.map +0 -1
@@ -0,0 +1,72 @@
1
+ import { defineConfig } from 'vitepress';
2
+ import { groupIconMdPlugin, groupIconVitePlugin } from 'vitepress-plugin-group-icons';
3
+
4
+ export default defineConfig({
5
+ title: 'Reactive Route',
6
+ description: 'Config-based routing for different frameworks',
7
+ base: '/reactive-route/',
8
+ head: [['link', { rel: 'icon', href: '/file.svg' }]],
9
+ markdown: {
10
+ config(md) {
11
+ md.use(groupIconMdPlugin);
12
+ },
13
+ },
14
+ vite: {
15
+ plugins: [groupIconVitePlugin()],
16
+ },
17
+ themeConfig: {
18
+ logo: '/file.svg',
19
+ nav: [
20
+ { text: 'Home', link: '/' },
21
+ { text: 'Guide', link: '/guide/', activeMatch: '/guide/' },
22
+ { text: 'Examples', link: '/examples/react', activeMatch: '/examples/' },
23
+ ],
24
+ sidebar: {
25
+ '/guide/': [
26
+ {
27
+ text: 'Introduction',
28
+ items: [
29
+ { text: 'What is Reactive Route?', link: '/guide/' },
30
+ { text: 'Getting Started', link: '/guide/getting-started' },
31
+ ],
32
+ },
33
+ {
34
+ text: 'Core Concepts',
35
+ items: [
36
+ { text: 'Routes Configuration', link: '/guide/routes-configuration' },
37
+ { text: 'Router Configuration', link: '/guide/router-configuration' },
38
+ { text: 'Router Component', link: '/guide/router-component' },
39
+ { text: 'SSR', link: '/guide/ssr' },
40
+ { text: 'Advanced', link: '/guide/advanced' },
41
+ ],
42
+ },
43
+ {
44
+ text: 'Framework Integration',
45
+ items: [
46
+ { text: 'React', link: '/guide/react' },
47
+ { text: 'Preact', link: '/guide/preact' },
48
+ { text: 'Solid.js', link: '/guide/solid' },
49
+ ],
50
+ },
51
+ ],
52
+ '/examples/': [
53
+ {
54
+ text: 'Examples',
55
+ items: [
56
+ { text: 'React', link: '/examples/react' },
57
+ { text: 'Preact', link: '/examples/preact' },
58
+ { text: 'Solid.js', link: '/examples/solid' },
59
+ ],
60
+ },
61
+ ],
62
+ },
63
+ search: {
64
+ provider: 'local',
65
+ },
66
+ socialLinks: [{ icon: 'github', link: 'https://github.com/dkazakov8/reactive-route' }],
67
+ footer: {
68
+ message: 'Released under the MIT License.',
69
+ copyright: 'Copyright © 2023-present Dmitry Kazakov',
70
+ },
71
+ },
72
+ });
@@ -0,0 +1,9 @@
1
+ :root {
2
+ --vp-c-brand-1: #6231b6;
3
+ --vp-button-brand-bg: #6231b6;
4
+ --vp-button-brand-hover-bg: #542a9c;
5
+ }
6
+
7
+ :root.dark {
8
+ --vp-code-color: #bb9ee1;
9
+ }
@@ -0,0 +1,5 @@
1
+ import Theme from 'vitepress/theme';
2
+ import 'virtual:group-icons.css';
3
+ import './custom.css';
4
+
5
+ export default Theme;
@@ -0,0 +1,22 @@
1
+ # Preact Example
2
+
3
+ To use it follow these steps:
4
+
5
+ ```shell
6
+ git clone https://github.com/dkazakov8/reactive-route.git
7
+ cd ./reactive-route/examples/preact
8
+ pnpm install
9
+ ```
10
+
11
+ This example is configured to use `pnpm` by default, but you may choose your own package manager
12
+ by editing `packageManager` field in `package.json`.
13
+
14
+ Next, choose the mode and reactivity system to start:
15
+
16
+ - `pnpm run mobx` - CSR (Client rendering only) for MobX
17
+ - `pnpm run observable` - CSR (Client rendering only) for Observable
18
+ - `pnpm run ssr-mobx` - SSR for MobX
19
+ - `pnpm run ssr-observable` - SSR for Observable
20
+
21
+ Note, that wrapping of components in `observer` is made by the ESBuild bundler in this example.
22
+ In your own projects, remember to follow the relevant [Framework Integration](/guide/preact).
@@ -0,0 +1,22 @@
1
+ # React Example
2
+
3
+ To use it follow these steps:
4
+
5
+ ```shell
6
+ git clone https://github.com/dkazakov8/reactive-route.git
7
+ cd ./reactive-route/examples/react
8
+ pnpm install
9
+ ```
10
+
11
+ This example is configured to use `pnpm` by default, but you may choose your own package manager
12
+ by editing `packageManager` field in `package.json`.
13
+
14
+ Next, choose the mode and reactivity system to start:
15
+
16
+ - `pnpm run mobx` - CSR (Client rendering only) for MobX
17
+ - `pnpm run observable` - CSR (Client rendering only) for Observable
18
+ - `pnpm run ssr-mobx` - SSR for MobX
19
+ - `pnpm run ssr-observable` - SSR for Observable
20
+
21
+ Note, that wrapping of components in `observer` is made by the ESBuild bundler in this example.
22
+ In your own projects, remember to follow the relevant [Framework Integration](/guide/react).
@@ -0,0 +1,21 @@
1
+ # Solid.js Example
2
+
3
+ To use it follow these steps:
4
+
5
+ ```shell
6
+ git clone https://github.com/dkazakov8/reactive-route.git
7
+ cd ./reactive-route/examples/solid
8
+ pnpm install
9
+ ```
10
+
11
+ This example is configured to use `pnpm` by default, but you may choose your own package manager
12
+ by editing `packageManager` field in `package.json`.
13
+
14
+ Next, choose the mode and reactivity system to start:
15
+
16
+ - `pnpm run solid` - CSR (Client rendering only) for Solid.js reactivity
17
+ - `pnpm run mobx` - CSR (Client rendering only) for MobX
18
+ - `pnpm run observable` - CSR (Client rendering only) for Observable
19
+ - `pnpm run ssr-solid` - SSR for Solid.js reactivity
20
+ - `pnpm run ssr-mobx` - SSR for MobX
21
+ - `pnpm run ssr-observable` - SSR for Observable
@@ -0,0 +1,79 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <!-- Created with Inkscape (http://www.inkscape.org/) -->
3
+
4
+ <svg
5
+ width="32"
6
+ height="32"
7
+ viewBox="0 0 32 32"
8
+ version="1.1"
9
+ id="svg1"
10
+ inkscape:version="1.4.2 (f4327f4, 2025-05-13)"
11
+ sodipodi:docname="ver-5.svg"
12
+ inkscape:export-filename="2.svg"
13
+ inkscape:export-xdpi="96"
14
+ inkscape:export-ydpi="96"
15
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
16
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
17
+ xmlns="http://www.w3.org/2000/svg"
18
+ xmlns:svg="http://www.w3.org/2000/svg">
19
+ <sodipodi:namedview
20
+ id="namedview1"
21
+ pagecolor="#ffffff"
22
+ bordercolor="#000000"
23
+ borderopacity="0.25"
24
+ inkscape:showpageshadow="2"
25
+ inkscape:pageopacity="0.0"
26
+ inkscape:pagecheckerboard="0"
27
+ inkscape:deskcolor="#d1d1d1"
28
+ inkscape:document-units="px"
29
+ showgrid="true"
30
+ inkscape:zoom="4"
31
+ inkscape:cx="28.75"
32
+ inkscape:cy="45"
33
+ inkscape:window-width="1920"
34
+ inkscape:window-height="1009"
35
+ inkscape:window-x="-8"
36
+ inkscape:window-y="-8"
37
+ inkscape:window-maximized="1"
38
+ inkscape:current-layer="layer1">
39
+ <inkscape:grid
40
+ id="grid1"
41
+ units="px"
42
+ originx="0"
43
+ originy="0"
44
+ spacingx="1"
45
+ spacingy="1"
46
+ empcolor="#0099e5"
47
+ empopacity="0.30196078"
48
+ color="#0099e5"
49
+ opacity="0.14901961"
50
+ empspacing="4"
51
+ enabled="true"
52
+ visible="true" />
53
+ </sodipodi:namedview>
54
+ <defs
55
+ id="defs1" />
56
+ <g
57
+ inkscape:label="Слой 1"
58
+ inkscape:groupmode="layer"
59
+ id="layer1">
60
+ <path
61
+ id="rect1"
62
+ style="fill:#000000;fill-opacity:1;stroke-width:0;stroke-dasharray:none"
63
+ d="m 3,2 v 4 4 2 h 8 V 8 6 h 11 v 8 H 3 v 4 10 2 h 8 v -4 -8 h 16 v -4 -1 h 2 V 7 H 27 V 6 2 Z m 19,24 v 4 h 7 v -4 z" />
64
+ <rect
65
+ style="fill:#000000;fill-opacity:1;stroke-width:0;stroke-dasharray:none"
66
+ id="rect113"
67
+ width="8"
68
+ height="4"
69
+ x="19"
70
+ y="20" />
71
+ <rect
72
+ style="fill:#000000;fill-opacity:1;stroke-width:0;stroke-dasharray:none"
73
+ id="rect114"
74
+ width="1"
75
+ height="4"
76
+ x="21"
77
+ y="26" />
78
+ </g>
79
+ </svg>
@@ -0,0 +1,131 @@
1
+ # Advanced
2
+
3
+ ## Redirects chain
4
+
5
+ This library fully supports unlimited redirects in SPA / SSR.
6
+
7
+ ```typescript [routes.ts]
8
+ const routes = createRoutes({
9
+ one: {
10
+ path: '/1',
11
+ oader: () => import('./pages/one'),
12
+ },
13
+ two: {
14
+ path: '/2',
15
+ loader: () => import('./pages/two'),
16
+ async beforeEnter(config) {
17
+ return config.redirect({ route: 'one' });
18
+ },
19
+ },
20
+ three: {
21
+ path: '/3',
22
+ loader: () => import('./pages/three'),
23
+ async beforeEnter(config) {
24
+ return config.redirect({ route: 'two' });
25
+ },
26
+ },
27
+ four: {
28
+ path: '/4',
29
+ loader: () => import('./pages/four'),
30
+ async beforeEnter(config) {
31
+ return config.redirect({ route: 'three' });
32
+ },
33
+ },
34
+
35
+ // Other routes
36
+ });
37
+ ```
38
+
39
+ In this case if user goes to `/4` he will be redirected to `/3` then `/2` then `/1`.
40
+ Browser's history and `router.routesHistory` will only have `['/1']`.
41
+ Also, chunks for pages four, three, two will not be loaded if you configured async chunks in your Bundler.
42
+
43
+ ## Watch and react to params / query changes
44
+
45
+ `router.currentRoute` is an observable, so you can use it inside autorun / reaction / effect of your stack.
46
+
47
+ ```tsx
48
+ import { TypeCurrentRoute } from 'reactive-route';
49
+ import { routes } from 'routes';
50
+
51
+ function MyComponent() {
52
+ const { router } = useContext(StoreContext);
53
+
54
+ const currentRoute = router.currentRoute as TypeCurrentRoute<typeof routes.tabs>;
55
+
56
+ // React + MobX way
57
+ useEffect(() => {
58
+ const disposer = autorun(() => {
59
+ // Always check the name. Because after redirecting the currentRoute
60
+ // will change, but this reaction is still alive, and the next route
61
+ // may not have params and query at all!
62
+ if (currentRoute.name !== 'tabs') return;
63
+
64
+ console.log(currentRoute.params.tab, currentRoute.query.foo);
65
+ })
66
+
67
+ return () => disposer();
68
+ }, []);
69
+
70
+ if (router.currentRoute.name !== 'tabs') return null;
71
+
72
+ if (router.currentRoute.params.tab === 'dashboard') {
73
+ return <Dashboard />
74
+ }
75
+
76
+ if (router.currentRoute.params.tab === 'table') {
77
+ return <Table />
78
+ }
79
+
80
+ return <ModeNotFound />;
81
+ }
82
+ ```
83
+
84
+ ## Prevent rerendering if pageId is the same
85
+
86
+ To Do
87
+
88
+ ## Modular exports
89
+
90
+ All the exports from your pages are written to the route config. You may read them in
91
+ `beforeSetPageComponent` prop of the `Router`. For example, when you use code-splitting and SSR
92
+ it's a good practice to extend some global RootStore or IoC container with page's stores:
93
+
94
+ ```tsx [pages/Home.tsx]
95
+ export const homeStore = {
96
+ foo: 'bar'
97
+ }
98
+
99
+ export default function Home() {
100
+ const { modularStores } = useContext(StoreContext);
101
+
102
+ return `Home ${modularStores.homeStore.foo}`;
103
+ }
104
+ ```
105
+
106
+ ```tsx [components/Router.tsx]
107
+ export function Router() {
108
+ const { router, modularStores } = useContext(StoreContext);
109
+
110
+ return (
111
+ <RouterLib
112
+ routes={routes}
113
+ router={router}
114
+ beforeSetPageComponent={(route) => {
115
+ if (route.otherExports?.homeStore) {
116
+ modularStores.homeStore = route.otherExports.homeStore;
117
+ }
118
+ }}
119
+ beforeUpdatePageComponent={() => {
120
+ if (modularStores.homeStore) {
121
+ modularStores.homeStore.destroy();
122
+ modularStores.homeStore = null;
123
+ }
124
+ }}
125
+ />
126
+ );
127
+ }
128
+ ```
129
+
130
+ This way on hydration server can serialize `modularStores.homeStore` and the client can easily
131
+ hydrate it on the first render. This mechanism can also be used in other useful scenarios.
@@ -0,0 +1,139 @@
1
+ # Getting Started
2
+
3
+ This guide will help you set up Reactive Route in your application and create your first routes.
4
+
5
+ ### Installation
6
+
7
+ The package includes the core router, React and Solid.js implementations, and adapters for different state management solutions.
8
+ Note that every combination requires corresponding libraries to be installed in your project.
9
+
10
+ ::: code-group
11
+ ```sh [npm]
12
+ npm i reactive-route
13
+ ```
14
+
15
+ ```sh [yarn]
16
+ yarn add reactive-route
17
+ ```
18
+
19
+ ```sh [pnpm]
20
+ pnpm add reactive-route
21
+ ```
22
+ :::
23
+
24
+ ### Modules map
25
+
26
+ ```typescript
27
+ import { createRoutes, createRouter } from 'reactive-route';
28
+ import { Router } from 'reactive-route/react';
29
+ import { Router } from 'reactive-route/solid';
30
+ import { Router } from 'reactive-route/preact';
31
+ import { adapters } from 'reactive-route/adapters/mobx-react';
32
+ import { adapters } from 'reactive-route/adapters/mobx-preact';
33
+ import { adapters } from 'reactive-route/adapters/mobx-solid';
34
+ import { adapters } from 'reactive-route/adapters/solid';
35
+ import { adapters } from 'reactive-route/adapters/kr-observable-react';
36
+ import { adapters } from 'reactive-route/adapters/kr-observable-preact';
37
+ import { adapters } from 'reactive-route/adapters/kr-observable-solid';
38
+ ```
39
+
40
+ ## Basic Setup
41
+
42
+ ### 1. Create a Router Store and Define Your Routes
43
+
44
+ First, create a router store using the `createRouter` function and
45
+ your routes configuration using the `createRoutes` function:
46
+
47
+ ```typescript [router.ts]
48
+ import { createRoutes, createRouter } from 'reactive-route';
49
+ import { adapters } from 'reactive-route/adapters/{reactive-system}';
50
+
51
+ const routes = createRoutes({
52
+ home: {
53
+ path: '/',
54
+ loader: () => import('./pages/home'),
55
+ },
56
+ user: {
57
+ path: '/user/:id',
58
+ params: {
59
+ id: (value) => /^\d+$/.test(value),
60
+ },
61
+ query: {
62
+ phone: (value) => value.length > 0 && value.length < 10,
63
+ },
64
+ loader: () => import('./pages/user'),
65
+ },
66
+ notFound: {
67
+ path: '/not-found',
68
+ props: { errorCode: 404 },
69
+ loader: () => import('./pages/error'),
70
+ },
71
+ internalError: {
72
+ path: '/internal-error',
73
+ props: { errorCode: 500 },
74
+ loader: () => import('./pages/error'),
75
+ },
76
+ });
77
+
78
+ // If you prefer Context and SSR
79
+ export function getRouter() {
80
+ return createRouter({ routes, adapters });
81
+ }
82
+
83
+ // If you prefer singletons
84
+ export const router = createRouter({ routes, adapters })
85
+ ```
86
+
87
+ Pages `notFound` and `internalError` are required for error handling in the library.
88
+
89
+ The recommended way is to use Context to pass it to UI components to avoid circular dependencies,
90
+ multiple instances and add the possibility of SSR.
91
+
92
+ ```typescript [StoreContext.tsx]
93
+ import { createContext } from '{ui-library}';
94
+
95
+ import { getRouter } from './router';
96
+
97
+ export const StoreContext = createContext(
98
+ undefined as unknown as { router: ReturnType<typeof getRouter> }
99
+ );
100
+ ```
101
+
102
+ ### 2. Set Up the Router Component
103
+
104
+ Create a custom Router component that uses the context to access the router store:
105
+
106
+ ```tsx [components/Router.tsx]
107
+ import { useContext } from '{ui-library}';
108
+ import { Router as RouterLib } from 'reactive-route/{ui-library}';
109
+
110
+ import { StoreContext } from './StoreContext';
111
+
112
+ export function Router() {
113
+ const { router } = useContext(StoreContext);
114
+
115
+ return <RouterLib router={router} />;
116
+ }
117
+ ```
118
+
119
+ ### 3. Initialize the router and render
120
+
121
+ ```tsx [client.tsx]
122
+ import { StoreContext } from './StoreContext';
123
+ import { getRouterStore } from './router';
124
+ import { Router } from './components/Router';
125
+
126
+ const router = getRouterStore();
127
+
128
+ await router.restoreFromURL({
129
+ pathname: location.pathname + location.search,
130
+ });
131
+
132
+ // the implementation is dependent on the UI library
133
+ render(
134
+ element,
135
+ <StoreContext.Provider value={{ router }}>
136
+ <Router />
137
+ </StoreContext.Provider>
138
+ );
139
+ ```
@@ -0,0 +1,44 @@
1
+ # What is Reactive Route?
2
+
3
+ ![coverage](https://github.com/dkazakov8/reactive-route/blob/master/assets/coverage.svg)
4
+ [![npm](https://img.shields.io/npm/v/reactive-route)](https://www.npmjs.com/package/reactive-route)
5
+ ![size-core](https://github.com/dkazakov8/reactive-route/blob/master/assets/core.svg)
6
+ ![size-react](https://github.com/dkazakov8/reactive-route/blob/master/assets/react.svg)
7
+ ![size-preact](https://github.com/dkazakov8/reactive-route/blob/master/assets/preact.svg)
8
+ ![size-solid](https://github.com/dkazakov8/reactive-route/blob/master/assets/solid.svg)
9
+
10
+ Reactive Route is a lightweight, flexible, and reactive router for JavaScript applications.
11
+
12
+ ### Framework and State Management Agnostic
13
+
14
+ The core routing logic is framework-agnostic, allowing it to be used with different UI frameworks and
15
+ state management solutions. Currently, Reactive Route provides official implementations for:
16
+
17
+ - React + MobX
18
+ - React + Observable
19
+ - Preact (no compat) + MobX
20
+ - Preact (no compat) + Observable
21
+ - Solid.js + Solid.js reactivity
22
+ - Solid.js + MobX
23
+ - Solid.js + Observable
24
+ - Vue + Vue reactivity (package in development)
25
+
26
+ ### Key Advantages
27
+
28
+ Reactive Route offers several advantages that make it a powerful choice for routing in modern web applications:
29
+
30
+ - **Lifecycle Hooks**: Built-in `beforeEnter` and `beforeLeave` hooks allow you to control navigation flow, perform authentication checks, load data, and handle unsaved changes.
31
+
32
+ - **Dynamic Component Loading**: Supports dynamically loaded components through async imports (e.g., `() => import('./pages/Home')`), enabling code splitting and improving application performance.
33
+
34
+ - **Modular Data Integration**: Supports dynamically loaded modular stores and other data for pages, making state management more organized and efficient.
35
+
36
+ - **Server-Side Rendering**: Full SSR support for all the supported frameworks, ensuring optimal performance and SEO benefits.
37
+
38
+ - **Parameter Validation**: Ensures that every dynamic parameter from the URL has a validator, preventing invalid routes and improving application robustness.
39
+
40
+ - **TypeScript Integration**: Comprehensive TypeScript support for routes, dynamic parameters, and search queries, providing excellent developer experience and type safety.
41
+
42
+ - **Separation of Concerns**: Functions as a centralized separate layer, eliminating the need for markup like `<Route path="..." />` inside components and keeping your component tree clean.
43
+
44
+ In the following sections, we'll explore how to install and use Reactive Route in your applications.
@@ -0,0 +1,33 @@
1
+ # Preact Integration
2
+
3
+ ## Mobx
4
+
5
+ The relevant imports are as follows
6
+
7
+ ```typescript
8
+ import { Router } from 'reactive-route/preact';
9
+ import { adapters } from 'reactive-route/adapters/mobx-preact';
10
+ ```
11
+
12
+ You should ensure that packages `mobx`, `mobx-react-lite` are installed.
13
+
14
+ If you use `mobx-react` instead of `mobx-react-lite` you may create an alias in your bundler or
15
+ pass your own adapters with similar implementation but `observer` taken from `mobx-react`.
16
+
17
+ Be sure to wrap your components which read observable router parameters into `observer` (if you use
18
+ MobX this is presumably already done).
19
+
20
+ ## Observable
21
+
22
+ The relevant imports are as follows
23
+
24
+ ```typescript
25
+ import { Router } from 'reactive-route/preact';
26
+ import { adapters } from 'reactive-route/adapters/kr-observable-preact';
27
+ ```
28
+
29
+ You should ensure that package `kr-observable` is installed.
30
+
31
+ Be sure to wrap your components which read observable router parameters into `observer` (if you use
32
+ Observable this is presumably already done).
33
+
@@ -0,0 +1,33 @@
1
+ # React Integration
2
+
3
+ ## Mobx
4
+
5
+ The relevant imports are as follows
6
+
7
+ ```typescript
8
+ import { Router } from 'reactive-route/react';
9
+ import { adapters } from 'reactive-route/adapters/mobx-react';
10
+ ```
11
+
12
+ You should ensure that packages `mobx`, `mobx-react-lite` are installed.
13
+
14
+ If you use `mobx-react` instead of `mobx-react-lite` you may create an alias in your bundler or
15
+ pass your own adapters with similar implementation but `observer` taken from `mobx-react`.
16
+
17
+ Be sure to wrap your components which read observable router parameters into `observer` (if you use
18
+ MobX this is presumably already done).
19
+
20
+ ## Observable
21
+
22
+ The relevant imports are as follows
23
+
24
+ ```typescript
25
+ import { Router } from 'reactive-route/react';
26
+ import { adapters } from 'reactive-route/adapters/kr-observable-react';
27
+ ```
28
+
29
+ You should ensure that package `kr-observable` is installed.
30
+
31
+ Be sure to wrap your components which read observable router parameters into `observer` (if you use
32
+ Observable this is presumably already done).
33
+
@@ -0,0 +1,67 @@
1
+ # Router Component Configuration
2
+
3
+ The router is the central piece that manages the state of the router and provides methods for navigation. It's created using the `createRouter` function.
4
+
5
+ ## Creating a Router Component
6
+
7
+ ```tsx [components/Router.tsx]
8
+ import { useContext } from '{ui-library}';
9
+ import { Router as RouterLib } from 'reactive-route/{ui-library}';
10
+
11
+ import { StoreContext } from './StoreContext';
12
+
13
+ export function Router() {
14
+ const { router } = useContext(StoreContext);
15
+
16
+ return <RouterLib router={router} />;
17
+ }
18
+ ```
19
+
20
+ The `Router` accepts these props:
21
+
22
+ | Property | Type | Description |
23
+ |-----------------------------|----------------------------------------|------------------------------------------------------------------------------------------------------------------|
24
+ | `router` | `ReturnType<typeof createRouter>` | The router configuration |
25
+ | `beforeMount` | `() => void` | This function is called once on Router Component initiation, before any rendering (optional) |
26
+ | `beforeUpdatePageComponent` | `() => void` | This function is called when page component is changed, before `beforeSetPageComponent` and rendering (optional) |
27
+ | `beforeSetPageComponent` | `(componentConfig: TypeRoute) => void` | This function is called when page component is loaded, before rendering (optional) |
28
+
29
+ ```tsx [components/Router.tsx]
30
+ import { useContext } from '{ui-library}';
31
+ import { Router as RouterLib } from 'reactive-route/{ui-library}';
32
+
33
+ import { routes } from '../routes';
34
+ import { StoreContext } from './StoreContext';
35
+
36
+ export function Router() {
37
+ const { router } = useContext(StoreContext);
38
+
39
+ return (
40
+ <RouterLib
41
+ routes={routes}
42
+ router={router}
43
+ beforeMount={() => {
44
+ // Router just mounted
45
+ }}
46
+ beforeUpdatePageComponent={() => {
47
+ // some new page will be rendered soon (not called on first render!)
48
+ // You may stop async actions and clear modular stores here
49
+
50
+ cancelExecutingApi();
51
+ cancelExecutingActions();
52
+ someStore.reset();
53
+ }}
54
+ beforeSetPageComponent={(route) => {
55
+ // some page will be rendered soon
56
+ // You may initiate modular stores here
57
+
58
+ console.log(route); // shows which page will be loaded
59
+
60
+ const myPageStore = route.otherExports?.myPageStore;
61
+ }}
62
+ />
63
+ );
64
+ }
65
+ ```
66
+
67
+ There are more examples of Router Component lifecycle in the [Advanced](/guide/advanced) section.