Skip to content

Commit 63f4a9c

Browse files
committed
Add code recipes
1 parent ef51005 commit 63f4a9c

File tree

1 file changed

+158
-0
lines changed

1 file changed

+158
-0
lines changed

Diff for: docs/isomorphic-routing-with-react-and-express.md

+158
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# Isomorphic (universal) routing with React and Express
2+
3+
```js
4+
// src/history.js
5+
import createBrowserHistory from 'history/createBrowserHistory';
6+
export default createBrowserHistory();
7+
```
8+
9+
```jsx
10+
// src/routes.js
11+
import React from 'react';
12+
import history from './history';
13+
14+
function onClick(event) {
15+
event.preventDefault(); // prevent full page reload
16+
history.push(event.currentTarget.getAttribute('href')); // do SPA navigation
17+
}
18+
19+
export default {
20+
path: '/',
21+
children: [
22+
{
23+
path: '/',
24+
action() {
25+
return {
26+
title: 'Welcome!',
27+
component: (
28+
<main>
29+
<h1>Hello, World!</h1>
30+
<nav>
31+
Navigation:
32+
<ul>
33+
<li><a href="/" onClick={onClick}>Home</a></li>
34+
<li><a href="/about" onClick={onClick}>About Us</a></li>
35+
<li><a href="/users" onClick={onClick}>Users</a></li>
36+
<li><a href="/articles" onClick={onClick}>Articles</a></li>
37+
<li><a href="/404" onClick={onClick}>404</a></li>
38+
</ul>
39+
</nav>
40+
</main>
41+
),
42+
};
43+
},
44+
},
45+
{
46+
path: '/about',
47+
action() {
48+
return {
49+
title: 'About Us',
50+
component: <h1>About Us</h1>,
51+
};
52+
},
53+
},
54+
{
55+
path: '/users',
56+
children: [
57+
{
58+
path: '/',
59+
async action() {
60+
const users = await fetch('/api/users');
61+
return {
62+
title: 'Users',
63+
component: <Users users={users} />,
64+
};
65+
},
66+
},
67+
{
68+
path: '/:user',
69+
async action({ params }) {
70+
const user = await fetch(`/api/user/${params.user}`);
71+
return {
72+
title: user.name,
73+
component: <User user={user} />,
74+
};
75+
},
76+
}
77+
],
78+
},
79+
{
80+
path: '/articles',
81+
async action() {
82+
const articles = await fetch(
83+
'https://gist.githubusercontent.com/koistya/a32919e847531320675764e7308b796a' +
84+
'/raw/fcbb12e60f8e664240c66bedd747978b16781231/articles.json'
85+
);
86+
return {
87+
title: 'Articles',
88+
component: (
89+
<main>
90+
<h1>Articles</h1>
91+
<ul>
92+
{articles.map(article =>
93+
<li><a href={article.url}>{article.title}</a></li>
94+
)}
95+
</ul>
96+
</main>
97+
),
98+
};
99+
},
100+
},
101+
{
102+
path: '*', // wildcard route (must go last)
103+
action() {
104+
return {
105+
title: 'Page Not Found',
106+
component: <h1>Not Found</h1>,
107+
};
108+
},
109+
},
110+
],
111+
};
112+
```
113+
114+
```js
115+
// src/client.js
116+
import UniversalRouter from 'universal-router';
117+
import ReactDOM from 'react-dom';
118+
import history from './history';
119+
import routes from './routes';
120+
121+
function render(location) {
122+
UniversalRouter.resolve(routes, location.pathname).then(route => {
123+
document.title = route.title;
124+
ReactDOM.render(route.component, document.body);
125+
});
126+
}
127+
128+
render(history.location); // initialize the app
129+
history.listen(location => render); // listen for client-side navigation
130+
```
131+
132+
```js
133+
// src/server.js
134+
import 'node-fetch'; // Fetch polyfill
135+
import express from 'express';
136+
import UniversalRouter from 'universal-router';
137+
import ReactDOM from 'react-dom/server';
138+
import routes from './routes';
139+
140+
const app = express();
141+
const port = 3000;
142+
143+
app.get('*', (req, res, next) => {
144+
UniversalRouter.resolve(routes, req.path).then(route => {
145+
res.send(
146+
`<!doctype html>
147+
<html>
148+
<head><title>${route.title}</title></head>
149+
<body>${ReactDOM.renderToString(route.component)}</body>
150+
</html>`
151+
);
152+
});
153+
});
154+
155+
app.listen(port, () => {
156+
console.log(`The server is running at http://localhost:${port}/`);
157+
});
158+
```

0 commit comments

Comments
 (0)