fridays / next-routes

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

Allow pass default parameters to routes #72

Closed acanimal closed 6 years ago

acanimal commented 7 years ago

This PR adds support for a fourth parameter that allows to set default query param values, for example:

routes.add({
  name: 'some_name',
  page: 'some_page',
  pattern: '/some/pattern/:paramA/:paramB',
  params: {
    paramA: 'some_default_value',
    paramC: 'this do not exists in the pattern'
  }
});
coveralls commented 7 years ago

Coverage Status

Coverage decreased (-0.5%) to 99.539% when pulling 808f652ce47638d396736bdde80be7958d72375f on acanimal:default-params into c63095e2d11d03433a8bc062edfb7f83036db212 on fridays:master.

fridays commented 7 years ago

Thanks for contributing!

It seems the defaults are applied after matching a URL and parsing its params. But that's too late, because the route wouldn't be found without the params in the first place. paramC from your example is not part of the URL so it should just be set in the component.

I wondered if it could be useful for generating URLs by route name, so it would use defaults when you don't provide all params. But the PR doesn't apply defaults in this case. And it could be done easily with a HOC, so I'm not sure if we should extend the API for this case. cc @HaNdTriX

If I missed something, please share more info on use cases!

acanimal commented 7 years ago

The params property is a mean for default parameters and the goal is to have a way to supply default values when a parameter is not present while the pattern continues to be what determines where we go (which page loads).

In the previous example:

routes.add({
  name: 'some_name',
  page: 'some_page',
  pattern: '/some/pattern/:paramA/:paramB',
  params: {
    paramA: 'some_default_value',
    paramC: 'this do not exists in the pattern'
  }
});

The params paramA and paramB are mandatory, they must be present in the URL to match. In addition paramC is added to the set of query params.

In another example like:

routes.add({
  name: 'some_name',
  page: 'some_page',
  pattern: '/some/pattern/:paramA?',
  params: {
    paramA: 'some_default_value',
  }
});

where paramA is optional we can set a default value for it when is not present.

fridays commented 7 years ago

Why not do it in the component?

Given /some/pattern/:paramA/:paramB?

const Index = ({
  url: {
    query: {
      paramA,
      paramB = 'default value',
      paramC = 'not in url'
    }
  }
}) => <div>{paramA} {paramB} {paramC}</div>

Or async:

const Index = ({
  paramA,
  paramB,
  paramC
}) => <div>{paramA} {paramB} {paramC}</div>

Index.getInitialProps = async ({query}) => ({
  paramB: 'default value',
  ...query,
  paramC: await Promise.resolve('not in url')
})
acanimal commented 7 years ago

In my case the same component can be rendered from many different routes with different shapes and parameters.

fridays commented 7 years ago

It should still be possible (and preferable) in the component. Wouldn't that work in your case?