- Step 1: Basic Routing
- Step 2: Asynchronous Routes
- Step 3: Parameterized Routes
- Step 4: Handling Redirects
- Step 5: Setting Page Title and Meta Tags
- Step 6: Code Splitting
- Step 7: Nested Routes
- Step 8: Integration with Flux
- Step 9: Server-side Rendering
In its simplest form the routing looks like a collection of URLs where each URL is mapped to a React component:
// client.js
import React from 'react';
import Layout from './components/Layout';
import HomePage from './components/HomePage';
import AboutPage from './components/AboutPage';
import NotFoundPage from './components/NotFoundPage';
import ErrorPage from './components/ErrorPage';
const routes = {
'/': <Layout><HomePage /></Layout>,
'/about': <Layout><AboutPage /></Layout>
};
const container = document.getElementById('app');
function render() {
try {
const path = window.location.hash.substr(1) || '/';
const component = routes[path] || <NotFoundPage />;
React.render(component, container);
} catch (err) {
React.render(<ErrorPage {...err} />, container);
}
}
window.addEventListener('hashchange', () => render());
render();
Just wrap React components inside your routes into asynchronous functions:
import React from 'react';
import fetch from './core/fetch';
import Layout from './components/Layout';
import HomePage from './components/HomePage';
import AboutPage from './components/AboutPage';
import NotFoundPage from './components/NotFoundPage';
import ErrorPage from './components/ErrorPage';
const routes = {
'/': async () => {
const response = await fetch('/graphql?query={content(path:"/"){title,html}}');
const data = await response.json();
return <Layout><HomePage {...data} /></Layout>
},
'/about': async () => {
const response = await fetch('/graphql?query={content(path:"/about"){title,html}}');
const data = await response.json();
return <Layout><AboutPage {...data} /></Layout>;
}
};
const container = document.getElementById('app');
async function render() {
try {
const path = window.location.hash.substr(1) || '/';
const route = routes[path];
const component = route ? await route() : <NotFoundPage />;
React.render(component, container);
} catch (err) {
React.render(<ErrorPage {...err} />, container);
}
}
window.addEventListener('hashchange', () => render());
render();
(1) Convert the list of routes from hash table to an array, this way the
order of routes will be preserved. (2) Wrap this collection into a Router
class, where you can put .match(url)
async method. (3) Use path-to-regexp
to convert Express-like path strings into regular expressions which are used
for matching URL paths to React components.
import React from 'react';
import Router from 'react-routing/src/Router';
import fetch from './core/fetch';
import Layout from './components/Layout';
import ProductListing from './components/ProductListing';
import ProductInfo from './components/ProductInfo';
import NotFoundPage from './components/NotFoundPage';
import ErrorPage from './components/ErrorPage';
const router = new Router(on => {
on('/products', async () => {
const response = await fetch('/graphql?query={products{id,name}}');
const data = await response.json();
return <Layout><ProductListing {...data} /></Layout>
});
on('/products/:id', async ({ params }) => {
const response = await fetch('/graphql?query={product(id:"${params.id}"){name,summary}}');
const data = await response.json();
return <Layout><ProductInfo {...data} /></Layout>;
});
}]);
const container = document.getElementById('app');
async function render() {
const state = { path: window.location.hash.substr(1) || '/' };
await router.dispatch(state, component => {
React.render(component, container);
});
}
window.addEventListener('hashchange', () => render());
render();
Coming soon. Stay tuned!