kriasoft/universal-router

Getting child route's params in middleware

kleinspire opened this issue · 2 comments

I'm submitting a ...

  • bug report
  • feature request
  • other (Please do not submit support requests here (below))

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.

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

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'),
    },
  ],
};