kriasoft / universal-router

A simple middleware-style router for isomorphic JavaScript web apps
https://www.kriasoft.com/universal-router/
MIT License
1.7k stars 103 forks source link

Getting child route's params in middleware #170

Closed kleinspire closed 5 years ago

kleinspire commented 5 years ago

I'm submitting a ...

There is currently no way to intercept params passed to the child route's context if the child route is resolved by context.next() inside a middleway.

const routes = {
  async action(context) {
    let route = await context.next();

   // No way to get username param here
    console.log(context.params); // equals to {};

    return route;
  },

  children: [
    {
      path: '/:username/posts',
      load: import('./UserPosts'),
    },
  ],
};

As the route params cannot be known ahead of time before resolving a route, one way is to automatically attach params to a route returned by context.next(). Another one is to update the context with last resolved route's params.

kleinspire commented 5 years ago

The best way would probably be calling context.next() like this:

let childRouteParams;

context.next((params) => { // Call next() with param intercept function
  childRouteParams = params; // We simply intercept params without changing them
  return params; // We could change params before sending them to the route, but we don't in this case.
});

// we now have childRoutParams we can use
kleinspire commented 5 years ago

Got it working with this:

import UniversalRouter from 'universal-router';
import routes from './routes';

export default new UniversalRouter(routes, {
  async resolveRoute(context, params) {
    if (Promise.resolve(context.route.load) == context.route.load) {
      const loaded = await context.route.load;
      return {
        ...loaded.default(context, params),
        params,
      };
    }
    if (typeof context.route.action === 'function') {
      const route = context.route.action(context, params);
      if (!route.isMiddleware) {
        route.params = params;
      }
      return route;
    }
    return undefined;
  },
});
const routes = {
  isMiddleware: true,

  async action(context) {
    let route = await context.next();

    console.log(route.params); // equals to { username : "jaz" };

    return route;
  },

  children: [
    {
      path: '/:username/posts',
      load: import('./UserPosts'),
    },
  ],
};