use-named-routes icon indicating copy to clipboard operation
use-named-routes copied to clipboard

Docs about server side usage?

Open th0r opened this issue 9 years ago • 7 comments

At first, thanks a lot for a great work, man!

Works like a charm but it took me a while to make it work server side with match() and I just want to share my solution here:

// app.server.js
import { match } from 'react-router';
import routes from './routes';
import createServerHistory from './createServerHistory';

// ...
match(
  { routes, history: createServerHistory(), location: req.url },
  function (error, redirectLocation, renderProps) { ... }
);
// createServerHistory.js
import { createMemoryHistory } from 'history';
import useNamedRoutes from 'use-named-routes';

import routes from './routes';

export default function createServerHistory() {
  return useNamedRoutes(createMemoryHistory)({ routes });
}

Maybe add docs about it to readme?

The only thing I don't like here is necessity to create new server history per request. This is because the underlying memory history created by createMemoryHistory is stateful but there is no need for this on server.

Do you know maybe someone has already created some kind of stateless createServerHistory and open sourced it?

th0r avatar Apr 07 '16 09:04 th0r

Drat, I knew I forgot something!

This is mostly right. A few caveats:

  • You should just use createMemoryHistory from React Router, instead of both the history version and useRouterHistory
  • match() creates a memory history no matter what: https://github.com/reactjs/react-router/blob/v2.0.1/modules/match.js#L23, so your concern about creating new server histories is irrelevant
  • Probably we should have some support for caching the route map (though other things like the parsed routes should be cached too)

I'll look into setting up support (for the cached route map to avoid rebuilding it on every request) and docs, but probably not until the weekend.

taion avatar Apr 07 '16 14:04 taion

You should just use createMemoryHistory from React Router, instead of both the history version and useRouterHistory

Ah, right! Haven't noticed that createMemoryHistory already contains useBasename and useQueries. Updated main post.

match() creates a memory history no matter what

The line you pointed to creates memory history only if history is not provided in the options object. Otherwise it would be impossible to add useNamedRoutes middleware and <Link> components wouldn't work.

th0r avatar Apr 07 '16 15:04 th0r

Right, so either you create one per request or match will. Either way you get a new history per request. You might be able to reuse a history across requests but I wouldn't recommend it.

taion avatar Apr 07 '16 15:04 taion

You might be able to reuse a history across requests but I wouldn't recommend it.

Why? What can go wrong if it'll be stateless? It will just be used to match urls and create location objects.

th0r avatar Apr 07 '16 15:04 th0r

It's probably okay but I'm not 100% sure, and we don't document the pattern anyway.

But either way that's orthogonal, right? If you're just using match({ location, routes }) and not using this package, you are creating a new history per request.

That part doesn't change with this package; you just move the history creation into your own code.

taion avatar Apr 07 '16 15:04 taion

@th0r What was your final solution here for setting it up on server-side? Following what you have above gives me the following error.

TypeError: history.listen is not a function

It seems that createServerHistory.listen is not a function..

Any thoughts/insights or your final solution would be most helpful!

oyeanuj avatar Jun 29 '16 03:06 oyeanuj

It seems that createServerHistory.listen is not a function

Seems like you're not callingcreateServerHistory but using it as-is. And another question: what is the history version you use? This snippet is not tested with v3, only v2.

th0r avatar Jun 29 '16 14:06 th0r