Closed secretfader closed 8 years ago
You can't really avoid it, it's like switch statements in a redux reducer. But there are different ways to go about it. https://github.com/router5/helpers contains a few helpers to avoiid doing .split('.')[0]
. You can also create your own helpers to help you find a component in a map, etc...
You can do stuff like the following:
import { startsWithSegment } from 'router5.helpers';
function Main(props) {
const { route } = props;
if (!route) {
return NotFound;
}
const startsWith = startsWithSegment(route.name);
if (startsWith('users')) return <Users />;
if (startsWith('home')) return <Home />;
/* etc... */
}
@troch That makes sense. What I like most about react-router
is there's one, clearly obvious way forward. Router5's strength is in the flexibility, but I also wonder if there should be an obvious solution for newcomers.
I'm working on a boilerplate for all of my new projects that uses Router5... I wonder, would you be open to extracting some of that work into an official guide? It's just fresh on my mind, as I'm working through the implementation.
@nicholaswyoung I would be totally open to that. I have been really busy recently (working a react / redux / router5 large scale app) and I haven't got the time to update docs and examples reflecting my own experience with it. So that could motivate me.
@troch I used your approach in the commit above, but I'm sure there are other ways that I can improve on the code that's in the repo. I'm also planning a series of blog posts on why I believe Router5 is the better solution, so I want to get this right before spreading the word.
@nicholaswyoung Please mention, when You're gonna release blog posts about it.
@pszek Will do, probably on this thread.
@pszek @troch I'm getting close to the ideal routing system over here. https://github.com/nicholaswyoung/react-boilerplate
It still has some kinks to be worked out, but I'm currently resolving issues.
Cool, that's pretty much what I do myself. I went back to using a router5 middleware for data, for two reasons: data requests are fired a call stack earlier and I can also block for universal pre-rendering.
import Router5 from 'router5';
import historyPlugin from 'router5-history';
import routes from './routes';
import { transitionPath } from 'router5';
export const getPageTitle = (routes) => (toState, fromState) => {
const { toActivate } = transitionPath(toState, fromState);
let pageTitle = 'XXXXX';
toActivate.forEach(segment => {
const routeSegment = routes.find(r => r.name === segment);
if (routeSegment.pageTitle) {
pageTitle = routeSegment.pageTitle + ' | XXXXX';
}
});
return pageTitle;
};
const pageTitleMiddleware = (routes) => (router) =>
(store, toState, fromState, done) => {
document.title = getPageTitle(routes)(toState, fromState);
done();
};
const routeDataMiddleware = (routes, waitForData) => (router) =>
(store, toState, fromState) => {
const { toActivate } = transitionPath(toState, fromState);
const dataPromises = toActivate
.map(segment => {
const routeSegment = routes.find(r => r.name === segment);
if (routeSegment && routeSegment.onActivate) {
return routeSegment.onActivate(store)(toState.params);
}
})
.filter(promise => promise !== undefined);
return waitForData ? Promise.all(dataPromises) : true;
};
const waitForData = __IS_BROWSER__;
const middlewares = [ routeDataMiddleware(routes, waitForData) ];
const defaultRoute = routes.find(route => route.default === true);
if (__IS_BROWSER__) {
middlewares.push(pageTitleMiddleware(routes));
}
export default function createRouter() {
const router = new Router5()
.add(routes)
.setOption('useHash', true)
.setOption('defaultRoute', defaultRoute)
.usePlugin(historyPlugin({ forceDeactivate: true }))
.useMiddleware(...middlewares);
return router;
}
@nicholaswyoung XO && AVA, like it even more!
@troch That's probably where I'll end up, eventually.
@Pszek And Enzyme (for testing React components).
Of course, I'm obligated to say this is the best boilerplate yet (because it's mine). But I can say without reservation that the tools I've preconfigured are genuinely the best.
Also: the onActivate
middleware should probably be it's own module. If @troch doesn't mind, I'll extract that into a module of it's own.
Oh yeah, I just put everything in a file, but please do make it a module. The main idea is that it's the easiest way to have an universal application.
@troch Do you have a preferred name, so it matches up with the existing router5 naming conventions?
No I don't :)
I love Router5. But now that I'm using it on multiple projects, the manual segment mapping is beginning to annoy me. This is something I find myself doing repeatedly. Here's an example:
There must be a better API for this behavior. I wonder if we can improve on it, and remove the need to manually split route names and pass the mapped component to
createElement
. This is something thatreact-router
got right, and I'd like to find a way to improve thereact-router5
project.