Skip to content

Commit 2fd9c38

Browse files
MonicaOlejniczakalbertogasparinliamqma
authored
Consolidate routers (#193)
* Consolidate Router component * Update docs/router/ssr.md * Listen to history in server environment only * Make ResourceContainer global Co-authored-by: Alberto Gasparin <agasparin@atlassian.com> Co-authored-by: Liam Ma <liam.q.ma@gmail.com>
1 parent 1240881 commit 2fd9c38

File tree

43 files changed

+530
-1318
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+530
-1318
lines changed

docs/_sidebar.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
* **Router**
1212

1313
- [Configuration](/router/configuration.md)
14-
- [Selection](/router/selection.md)
1514
- [State](/router/state.md)
1615
- [SSR](/router/ssr.md)
1716

docs/api/components.md

Lines changed: 12 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -29,82 +29,33 @@ import { appRoutes } from './routing';
2929

3030
### Router props
3131

32-
| prop | type | description |
33-
| ----------------- | ------------------------- | -------------------------------------------------------------------------------------------------- |
34-
| `routes` | `Routes[]` | Your application's routes |
35-
| `initialRoute` | `Route` | The route your application is initially showing |
36-
| `history` | `History` | The history instance for the router |
37-
| `basePath` | `string` | Base path string that will get prepended to all route paths |
38-
| `resourceContext` | `ResourceContext` | Custom contextual data that will be provided to all your resources' `getKey` and `getData` methods |
39-
| `resourceData` | `ResourceData` | Pre-resolved resource data. When provided, the router will not request resources on mount |
40-
| `onPrefetch` | `function(RouterContext)` | Called when prefetch is triggered from a Link |
41-
42-
## StaticRouter
43-
44-
If you are planning to render your application on the server, you must use the `StaticRouter` in your server side entry. The `StaticRouter` should only be used on server as it omits all browser-only resources. It does not require a `history` prop to be provided, instead, you simply need to provide the current `location` as a string. In order to achieve this, we recommend your server side application uses [`jsdom`](https://github.com/jsdom/jsdom).
45-
46-
```js
47-
// server-app.js
48-
import { StaticRouter } from 'react-resource-router';
49-
import { App } from '../components';
50-
import { appRoutes } from '../routing';
51-
52-
const { pathname, search } = window.location;
53-
const location = `${pathname}${search}`;
54-
55-
export const ServerApp = () => (
56-
<StaticRouter routes={appRoutes} location={location}>
57-
<App />
58-
</StaticRouter>
59-
);
60-
```
61-
62-
### StaticRouter props
63-
64-
| prop | type | description |
65-
| ---------- | ---------- | ----------------------------------------------------------- |
66-
| `routes` | `Routes[]` | Your application's routes |
67-
| `location` | `string` | The string representation of the app's current location |
68-
| `basePath` | `string` | Base path string that will get prepended to all route paths |
32+
| prop | type | description |
33+
| ----------------- | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
34+
| `routes` | `Routes[]` | Your application's routes |
35+
| `history` | `History` | The history instance for the router, if omitted memory history will be used (optional but recommended) |
36+
| `basePath` | `string` | Base path string that will get prepended to all route paths (optional) |
37+
| `initialRoute` | `Route` | The route your application is initially showing, it's a performance optimisation to avoid route matching cost on initial render(optional) |
38+
| `resourceContext` | `ResourceContext` | Custom contextual data that will be provided to all your resources' `getKey` and `getData` methods (optional) |
39+
| `resourceData` | `ResourceData` | Pre-resolved resource data. When provided, the router will not request resources on mount (optional) |
40+
| `onPrefetch` | `function(RouterContext)` | Called when prefetch is triggered from a Link (optional) |
6941

7042
## MemoryRouter
7143

7244
The `MemoryRouter` component can be used for your application's unit tests.
7345

7446
```js
7547
it('should send right props after render with routes', () => {
76-
mount(
77-
<MemoryRouter routes={[mockRoutes[0]]}>
78-
<RouterSubscriber>
79-
{({ history, location, routes, route, match, query }) => {
80-
expect(history).toEqual(mockHistory);
81-
expect(location).toEqual(mockLocation);
82-
expect(routes).toEqual(routes);
83-
expect(route).toEqual(
84-
expect.objectContaining({
85-
path: `/pathname`,
86-
})
87-
);
88-
expect(match).toBeTruthy();
89-
expect(query).toEqual({
90-
foo: 'bar',
91-
});
92-
93-
return <div>I am a subscriber</div>;
94-
}}
95-
</RouterSubscriber>
96-
</MemoryRouter>
97-
);
48+
render(<MemoryRouter routes={[mockRoutes[0]]}>{/* ... */}</MemoryRouter>);
9849
});
9950
```
10051

10152
### MemoryRouter props
10253

10354
| prop | type | description |
10455
| ---------- | ---------- | ----------------------------------------------------------- |
105-
| `routes` | `Routes[]` | Your application's routes |
106-
| `location` | `string` | The string representation of the app's current location |
10756
| `basePath` | `string` | Base path string that will get prepended to all route paths |
57+
| `location` | `string` | The string representation of the app's current location |
58+
| `routes` | `Routes[]` | Your application's routes |
10859

10960
## Link component
11061

docs/router/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
- **Router**
22

33
- [Configuration](./configuration.md)
4-
- [Selection](./selection.md)
54
- [State](./state.md)
65
- [SSR](./ssr.md)

docs/router/selection.md

Lines changed: 0 additions & 3 deletions
This file was deleted.

docs/router/ssr.md

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,28 @@ import { RouteComponent } from 'react-resource-router';
2222

2323
export const App = () => (
2424
<>
25+
<Navigation />
2526
<RouteComponent />
27+
<Footer />
2628
</>
2729
);
2830
```
2931

30-
The reason for this is that currently, you will need to use the [`Router`](#router-component) component on the client and the [`StaticRouter`](#staticrouter-component) component on the server. Following the above composition pattern will allow you to use the correct router in your server side entry and client side entry respectively. This could look something like the following examples:
32+
When you need to SSR your app, we need to pass different props to Router, as `createBrowserHistory` does not really work on server, so we recommend to use your own `MemoryHistory`
3133

3234
```js
3335
// server-app.js
34-
import { StaticRouter } from 'react-resource-router';
36+
import { createMemoryHistory } from 'history';
37+
import { Router } from 'react-resource-router';
3538
import { App } from '../components';
39+
import { routes } from '../routing/routes';
3640

37-
export const ServerApp = ({ location, routes }) => (
38-
<StaticRouter routes={routes} location={location}>
41+
export const ServerApp = ({ location }) => (
42+
<Router
43+
history={createMemoryHistory({ initialEntries: [location]} )}
44+
routes={routes}>
3945
<App />
40-
</StaticRouter>
46+
</Router>
4147
);
4248
```
4349

@@ -50,7 +56,7 @@ import { routes } from '../routing/routes';
5056
const history = createBrowserHistory();
5157

5258
export const ClientApp = () => (
53-
<Router routes={routes} history={history}>
59+
<Router history={history} routes={routes}>
5460
<App />
5561
</Router>
5662
);
@@ -60,21 +66,21 @@ export const ClientApp = () => (
6066

6167
Until React Suspense works on the server, we cannot do progressive rendering server side. To get around this, we need to `await` all resource requests to render our app _with all our resource data_ on the server.
6268

63-
Luckily the `StaticRouter` provides a convenient static method to do this for us.
69+
Luckily the `Router` provides a convenient static method to do this for us.
6470

6571
```js
6672
import { renderToString } from 'react-dom/server';
67-
import { StaticRouter } from 'react-resource-router';
73+
import { Router } from 'react-resource-router';
6874
import { routes } from '../routing/routes';
6975
import { ServerApp } from './app';
7076

7177
const renderToStringWithData = async ({ location }) => {
72-
await StaticRouter.requestResources({ location, routes });
78+
await Router.requestResources({ location, routes });
7379

74-
return renderToString(<ServerApp routes={routes} location={location} />);
80+
return renderToString(<ServerApp location={location} />);
7581
};
7682
```
7783

78-
Notice that we do not need to provide any `resourceData` object to the `ServerApp`, the `StaticRouter` handles this for us internally.
84+
Notice that we do not need to provide any `resourceData` object to the `ServerApp`, the `Router` handles this for us internally.
7985

80-
To prevent slow APIs from causing long renders on the server you can optionally pass in `timeout` as an option to `StaticRouter.requestResources`. If a route resource does not return within the specified time then its data and promise will be set to null.
86+
To prevent slow APIs from causing long renders on the server you can optionally pass in `timeout` as an option to `Router.requestResources`. If a route resource does not return within the specified time then its data and promise will be set to null.

examples/hash-routing/about.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React from 'react';
2+
3+
import { Link } from 'react-resource-router';
4+
5+
export const About = () => (
6+
<div>
7+
<h1>About</h1>
8+
<Link to="/">Go to home</Link>
9+
</div>
10+
);

examples/hash-routing/home.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React from 'react';
2+
3+
import { Link } from 'react-resource-router';
4+
5+
export const Home = () => (
6+
<div>
7+
<h1>Home</h1>
8+
<Link to="/about">Go to about</Link>
9+
</div>
10+
);

examples/hash-routing/index.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Example - Hash Routing</title>
5+
</head>
6+
7+
<body>
8+
<div id="root"></div>
9+
<script src="bundle.js" type="text/javascript"></script>
10+
</body>
11+
</html>

examples/hash-routing/index.tsx

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { createHashHistory as createHashHistory4 } from 'history';
2+
import { createHashHistory as createHashHistory5 } from 'history-5';
3+
import React from 'react';
4+
import { render } from 'react-dom';
5+
6+
import { About } from './about';
7+
import { Home } from './home';
8+
9+
import { Redirect, RouteComponent, Router } from 'react-resource-router';
10+
11+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
12+
const history4 = createHashHistory4();
13+
const history5 = createHashHistory5();
14+
const history = history5;
15+
16+
const routes = [
17+
{
18+
name: 'home',
19+
path: '/home',
20+
exact: true,
21+
component: () => <Home />,
22+
},
23+
{
24+
name: 'about',
25+
path: '/about',
26+
exact: true,
27+
component: () => <About />,
28+
},
29+
{
30+
name: 'default',
31+
path: '/*',
32+
exact: true,
33+
component: () => <Redirect to="/home" />,
34+
},
35+
];
36+
37+
const App = () => {
38+
return (
39+
<Router history={history} routes={routes}>
40+
<RouteComponent />
41+
</Router>
42+
);
43+
};
44+
45+
render(<App />, document.getElementById('root'));

examples/hydration/index.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,14 @@ import {
88
Router,
99
RouteComponent,
1010
createBrowserHistory,
11-
StaticRouter,
1211
} from 'react-resource-router';
1312

1413
const myHistory = createBrowserHistory();
1514

1615
const appRoutes = [homeRoute];
1716

1817
const getStateFromServer = async () => {
19-
// StaticRouter should only be used on Server!
20-
// It's used in Browser in this example for simplicity.
21-
const resourceData = await StaticRouter.requestResources({
18+
const resourceData = await Router.requestResources({
2219
location: '/',
2320
routes: appRoutes,
2421
});

0 commit comments

Comments
 (0)