fridays / next-routes

Universal dynamic routes for Next.js
MIT License
2.47k stars 230 forks source link

Support `parse` option to parse incoming params #49

Closed ajoslin closed 7 years ago

ajoslin commented 7 years ago

First, thanks for this. I've implemented it and it serves almost all of my needs.

I'd like to propose adding a feature: a parseParams function of some sort as an option.

I'm rewriting a legacy app that supports hundreds of urls. For example, there's one legacy route I must support that is /add-to-cart?qty=n&sku=n

In my components however, I don't expect a qty parameter. I expect quantity.

I've monkey-patched route.match to support a parseParams function, which takes the incoming query and transforms it:

nextRoutes.add(name, path, item.page)
const route = nextRoutes.routes[nextRoutes.routes.length - 1]

const _match = route.match
route.match = (path) => {
  let params = _match.call(route, path)
  return !params
    ? undefined
    : item.parseParams(params) // defaults to `identity`
}

Example of a parseParams function:

parseParams: (data) => ({
  sku: data.sku,
  quantity: data.qty,
  title: humanizeUrlParam(data.title)
})

Would next-routes be open to supporting this as part of the library? If so, I can open a PR.

fridays commented 7 years ago

Thanks for contributing! Please see if https://github.com/fridays/next-routes/pull/51 works in your case.

ajoslin commented 7 years ago

:+1: works for me.

fridays commented 7 years ago

Actually getInitialProps is the better place to do this, so it works on both client and server. Does something like this work for you?

static async getInitialProps ({query}) {
  return {
    sku: query.sku,
    quantity: query.qty,
    title: humanizeUrlParam(query.title)
  }
}
ajoslin commented 7 years ago

Yes, I'm using getInitialProps now. I ran into the same problem.

I preferred having everything in one file handled by one thing, but oh well. This isn't too bad, adding props to my universal "Layout HOC" that every page shares.

Example of what I settled on:

export default Layout(MyPageCmp, {
  parseQuery: Parser({
    path: s => (s || '').toLowerCase(),
    seo: true,
    title: ['seo', paramToTitle]
  })
})