@tinkoff/router 0.2.6 → 0.2.7

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 (2) hide show
  1. package/README.md +2 -276
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Routing library. It can work both on the server and on the client. Designed primarily for building isomorphic applications.
4
4
 
5
+ Link to complete Router documentation - https://tramvai.dev/docs/features/routing/overview/
6
+
5
7
  ## Installation
6
8
 
7
9
  You need to install `@tinkoff/router`:
@@ -13,285 +15,9 @@ yarn add @tinkoff/router
13
15
  And connect it to the project:
14
16
 
15
17
  ```tsx
16
- import { Router } from '@tinkoff/router';
17
-
18
- const router = new Router();
19
- ```
20
-
21
- ## Explanation
22
-
23
- Features:
24
-
25
- - The library supports options for working both on the server and on the client.
26
- - It is possible to use different client transition options: with or without SPA transitions.
27
- - There are Guards to check the availability of a route under specific conditions.
28
- - You can subscribe to different stages of the transition through hooks
29
- - Components and hooks for easy routing from react
30
-
31
- ### Server and client version
32
-
33
- It is enough just to import routing from the library itself and, based on the settings in package.json, the required version for the server or client will be returned
34
-
35
- ```ts
36
- import { Router } from '@tinkoff/router';
37
- ```
38
-
39
- ### Client routing with/without SPA transitions
40
-
41
- By default, routing with SPA transitions is enabled on the client. If you need to disable SPA transitions, you need to import a special version of the routing
42
-
43
- ```ts
44
18
  import { Router, SpaHistory } from '@tinkoff/router';
45
19
  import { NoSpaRouter } from '@tinkoff/router';
46
20
 
47
21
  const spaRouter = new Router({ history: new SpaHistory() });
48
22
  const noSpaRouter = new NoSpaRouter();
49
23
  ```
50
-
51
- ### Router Guards
52
-
53
- Guards allow you to control the availability of a particular route for a specific transition. From the guard, you can block the transition or initiate a redirect.
54
-
55
- ```ts
56
- import { NavigationGuard } from '@tinkoff/router';
57
-
58
- export const myGuard: NavigationGuard = async ({ to }) => {
59
- if (to.config.blocked) {
60
- return false; // block this transition
61
- }
62
-
63
- if (typeof to.config.redirect === 'string') {
64
- return to.config.redirect; // call a redirect to the specified page
65
- }
66
-
67
- if (typeof to.config.needAuth && !isAuth()) {
68
- return { url: '/login/', code: '302' }; // redirect to page with NavigateOptions
69
- }
70
-
71
- // if nothing is returned, the transition will be performed as usual
72
- };
73
-
74
- router.registerGuard(myGuard);
75
- ```
76
-
77
- #### Rules
78
-
79
- - guards are asynchronous and it execution will be awaited inside routing
80
- - all guards are running in parallel and they are all awaited
81
- - if several guars return something then the result from a guard that was registered early will be used
82
-
83
- #### Possible result
84
-
85
- The behaviour of routing depends on the result of executing guards functions and there result might be next:
86
-
87
- - if all of the guards returns `undefined` than navigation will continue executing
88
- - if any of the guards returns `false` than navigation is getting blocked and next action differs on server and client
89
- - if any of the guards returns `string` it is considered as url to which redirect should be happen
90
- - if any of the guards returns [`NavigateOptions`](#navigateoptions) interface, `url` property from it is considered as url to which redirect should be happen
91
-
92
- ### Transitions hooks
93
-
94
- Transition hooks allow you to perform your asynchronous actions at different stages of the transition.
95
-
96
- ```ts
97
- import { NavigationHook } from '@tinkoff/router';
98
-
99
- export const myHook: NavigationHook = async ({ from, to, url, fromUrl }) => {
100
- console.log(`navigating from ${from} to route ${to}`);
101
- };
102
-
103
- router.registerHook('beforeNavigate', myHook);
104
- ```
105
-
106
- #### Rules
107
-
108
- - all hooks from the same event are running in parallel
109
- - most of the hooks are asynchronous and are awaited inside router
110
- - if some error happens when running hook it will be logged to console but wont affect navigation (except for the `beforeResolve` hook - error for it will be rethrown)
111
-
112
- #### List of available hooks
113
-
114
- Async hooks:
115
-
116
- - [navigate hooks](#navigate-hooks) - asynchronous hooks only for navigate calls
117
- - [updateCurrentRoute hooks](#updatecurrentroute-hooks) - asynchronous hooks only for updateCurrentRoute calls
118
-
119
- Sync hooks:
120
-
121
- - `change` - runs when any of changes to current route\url happens
122
-
123
- ## API
124
-
125
- ### Getting data about the current route or url
126
-
127
- ```ts
128
- router.getCurrentRoute(); // will return the current route
129
- router.getCurrentUrl(); // will return the parsed version of the url of the current page
130
- ```
131
-
132
- ### Transition initiation
133
-
134
- There are two methods for initializing the navigation and updating the address bar in the browser. The main difference between these two methods is that one of them will launch a full-fledged transition with data updating and starting heavy data loading actions. The second method is mainly used to update the state for the current route: to update the query parameters on the page or change the dynamic parameters of the route itself.
135
-
136
- #### navigate
137
-
138
- Initiates a full transition, defining the next route and updating the state in the browser.
139
-
140
- ```ts
141
- router.navigate('/test');
142
- router.navigate({ url: './test', query: { a: '1' } });
143
- ```
144
-
145
- ##### navigate hooks
146
-
147
- - beforeResolve
148
- - beforeNavigate
149
- - afterNavigate
150
-
151
- ##### navigate workflow
152
-
153
- 1. `beforeResolve` hook
154
- 2. [guards](#router-guards)
155
- 3. `beforeNavigate`
156
- 4. `change`
157
- 5. `afterNavigate`
158
-
159
- #### updateCurrentRoute
160
-
161
- The transition is based on the current route (therefore this method cannot be called on the server) and allows you to simply update some data for the current page
162
-
163
- ```ts
164
- router.updateCurrentRoute({ params: { id: 'abc' } });
165
- router.updateCurrentRoute({ query: { a: '1' } });
166
- ```
167
-
168
- ##### updateCurrentRoute hooks
169
-
170
- - beforeUpdateCurrent
171
- - afterUpdateCurrent
172
-
173
- ##### updateCurrentRoute workflow
174
-
175
- 1. `beforeUpdateCurrent`
176
- 2. `change`
177
- 3. `afterUpdateCurrent`
178
-
179
- ### NavigateOptions
180
-
181
- Object that allows to specify transition options both to [navigate](#navigate) and [updateCurrentRoute](#updatecurrentroute) transitions
182
-
183
- - `code` - redirect code that is returned on server in case of redirects
184
- - `navigateState` - any additional data that is stored with route
185
-
186
- ### Working with query
187
-
188
- #### query option
189
-
190
- Allows you to set a search string for an url as an object via the `query` option when navigating. The previous query value will be cleared
191
-
192
- ```ts
193
- router.getCurrentUrl().query; // { с: 'c' }
194
-
195
- router.navigate({ query: { a: 'a', b: 'b' } });
196
- router.updateCurrentRoute({ query: { a: 'a', b: 'b' } });
197
-
198
- router.getCurrentUrl().query; // { a: 'a', b: 'b' }
199
- ```
200
-
201
- #### preserveQuery
202
-
203
- Allows you to keep the query value from the current navigation and use them in a new transition
204
-
205
- ```ts
206
- router.getCurrentUrl().query; // { с: 'c' }
207
-
208
- router.navigate({ query: { a: 'a' }, preserveQuery: true });
209
- router.updateCurrentRoute({ query: { a: 'a' }, preserveQuery: true });
210
-
211
- router.getCurrentUrl().query; // { a: 'a', c: 'c' }
212
- ```
213
-
214
- If you pass undefined as the value for a specific query key, then this value will be cleared in a new query:
215
-
216
- ```ts
217
- router.getCurrentUrl().query; // { a: 'a', b: 'b' }
218
-
219
- router.navigate({ query: { a: undefined, c: 'c' }, preserveQuery: true });
220
- router.updateCurrentRoute({ query: { a: undefined, c: 'c' }, preserveQuery: true });
221
-
222
- router.getCurrentUrl().query; // { b: 'b', c: 'c' }
223
- ```
224
-
225
- ### Constructor options
226
-
227
- - `trailingSlash` - do router should force all urls to end with slash. If `true` - force trailing slash for every path, `false` - force no trailing slash, `undefined` - trailing slash is specified by request and both trailing and not trailing slashes are used. By default value if `undefined`
228
- - `mergeSlashes` - replace several consecutive slashes by single slashes (slashes after protocol are still be with `//` after protocol name). By default is `false` - no merge for slashes.
229
-
230
- ### Integration with React
231
-
232
- Library has some useful React hooks and components for working with routing
233
-
234
- #### useRoute
235
-
236
- Returns current active route of the application
237
-
238
- ```ts
239
- import React from 'react';
240
- import { useRoute } from '@tinkoff/router';
241
-
242
- export const Component = () => {
243
- const route = useRoute();
244
-
245
- return <div>Route path: {route.actualPath}</div>;
246
- };
247
- ```
248
-
249
- #### useUrl
250
-
251
- Returns current active URL of the application
252
-
253
- ```ts
254
- import React from 'react';
255
- import { useUrl } from '@tinkoff/router';
256
-
257
- export const Component = () => {
258
- const url = useUrl();
259
-
260
- return <div>Url query: {JSON.stringify(url.query)}</div>;
261
- };
262
- ```
263
-
264
- #### useNavigate
265
-
266
- Creates a callback with a navigation call that can be passed to child components or used as an event handler
267
-
268
- ```ts
269
- export const Cmp = () => {
270
- const navigate = useNavigate('/test/');
271
-
272
- return <div onClick={navigate}>Test</div>;
273
- };
274
- ```
275
-
276
- ## How to
277
-
278
- ### Load route config from external api
279
-
280
- Use [transition hook](#transitions-hooks) `beforeResolve` and load routes config based on url.
281
-
282
- ```ts
283
- router.registerHook('beforeResolve', async (navigation) => {
284
- const route = await routeResolve(navigation);
285
-
286
- if (route) {
287
- router.addRoute(routeTransform(route));
288
- }
289
- });
290
- ```
291
-
292
- ### App behind proxy
293
-
294
- Router doesn't support proxy setup directly. But proxy still can be used with some limitations:
295
-
296
- - setup proxy server to pass requests to app with rewriting request and response paths. (E.g. for [nginx](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect))
297
- - it wont work as expected on spa navigation on client, so only option in this case is use the `NoSpaRouter`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tinkoff/router",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
4
4
  "description": "router",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",