universal-router icon indicating copy to clipboard operation
universal-router copied to clipboard

Full examples are missing

Open aurimus opened this issue 8 years ago • 3 comments

I am having hard time to figure out how to setup a full working react app. Are there any examples out there?


Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

aurimus avatar Feb 20 '17 09:02 aurimus

Based on https://github.com/kriasoft/react-starter-kit (ref #72) Universal (isomorphic) app example:

// src/history.js
import createBrowserHistory from 'history/createBrowserHistory';
export default createBrowserHistory();
// src/routes.js
import React from 'react';
import history from './history';

function onClick(event) {
  event.preventDefault(); // prevent full page reload
  history.push(event.currentTarget.getAttribute('href')); // do SPA navigation
}

export default {
  path: '/',
  children: [
    {
      path: '/',
      action() {
        return {
          title: 'Welcome!',
          component: (
            <main>
              <h1>Hello, World!</h1>
              <nav>
                Navigation:
                <ul>
                  <li><a href="/" onClick={onClick}>Home</a></li>
                  <li><a href="/about" onClick={onClick}>About Us</a></li>
                  <li><a href="/users" onClick={onClick}>Users</a></li>
                  <li><a href="/articles" onClick={onClick}>Articles</a></li>
                  <li><a href="/404" onClick={onClick}>404</a></li>
                </ul>
              </nav>
            </main>
          ),
        };
      },
    },
    {
      path: '/about',
      action() {
        return {
          title: 'About Us',
          component: <h1>About Us</h1>,
        };
      },
    },
    {
      path: '/users',
      children: [
        {
          path: '/',
          async action() {
            const users = await fetch('/api/users');
            return {
              title: 'Users',
              component: <Users users={users} />,
            };
          },
        },
        {
          path: '/:user',
          async action({ params }) {
            const user = await fetch(`/api/user/${params.user}`);
            return {
              title: user.name,
              component: <User user={user} />,
            };
          },
        }
      ],
    },
    {
      path: '/articles',
      async action() {
        const articles = await fetch(
          'https://gist.githubusercontent.com/koistya/a32919e847531320675764e7308b796a' +
          '/raw/fcbb12e60f8e664240c66bedd747978b16781231/articles.json'
        );
        return {
          title: 'Articles',
          component: (
            <main>
              <h1>Articles</h1>
              <ul>
                {articles.map(article =>
                  <li><a href={article.url}>{article.title}</a></li>
                )}
              </ul>
            </main>
          ),
        };
      },
    },
    {
      path: '*', // wildcard route (must go last)
      action() {
        return {
          title: 'Page Not Found',
          component: <h1>Not Found</h1>,
        };
      },
    },
  ],
};
// src/client.js
import UniversalRouter from 'universal-router';
import ReactDOM from 'react-dom';
import history from './history';
import routes from './routes';

function render(location) {
  UniversalRouter.resolve(routes, location.pathname).then(route => {
    document.title = route.title;
    ReactDOM.render(route.component, document.body);
  });
}

render(history.location); // initialize the app
history.listen(render); // listen for client-side navigation
// src/server.js
import 'node-fetch'; // Fetch polyfill
import express from 'express';
import UniversalRouter from 'universal-router';
import ReactDOM from 'react-dom/server';
import routes from './routes';

const app = express();
const port = 3000;

app.get('*', (req, res, next) => {
  UniversalRouter.resolve(routes, req.path).then(route => {
    res.send(
      `<!doctype html>
      <html>
        <head><title>${route.title}</title></head>
        <body>${ReactDOM.renderToString(route.component)}</body>
      </html>`
    );
  });
});

app.listen(port, () => {
  console.log(`The server is running at http://localhost:${port}/`);
});

frenzzy avatar Feb 20 '17 13:02 frenzzy

@frenzzy good example. beware of the small typo in history.listen which prevents this from working. The render function is not called.

simoneb avatar Mar 07 '17 23:03 simoneb

the last line of src/client.js should be

history.listen(location => render());

lol

frozenfung avatar Aug 14 '17 10:08 frozenfung