React-router: Allow an array of strings in <Route path>

Created on 12 Jan 2018  路  9Comments  路  Source: ReactTraining/react-router

This is a follow-up from #5393.

It would be nice if <Route path> could accept an array of strings instead of a single string. This would make it possible to render the same <Route> element at multiple different URLs as suggested here.

The reason #5393 was not merged is because there was a problem with the way the code worked with respect to relative routes. When this work is done, match.path should still be a string, not an array.

Most helpful comment

What needs to be done to remove this prop-types warning?

In the meantime, I patch this in my own codebase by overriding the default prop types.

For those of you reading this, here is what I do:

import { Route } from "react-router-dom"
import PropTypes from "prop-types"

Route.propTypes = {
  computedMatch: PropTypes.object,
  path: PropTypes.oneOfType([PropTypes.array, PropTypes.string]),
  exact: PropTypes.bool,
  strict: PropTypes.bool,
  sensitive: PropTypes.bool,
  component: PropTypes.func,
  render: PropTypes.func,
  children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
  location: PropTypes.object
}

All 9 comments

Thanks! Its work. But i got warning Failed prop type: Invalid proppathof typearraysupplied toRoute, expectedstring`.

It works but not as expected.
There is no props.match.params data for each path in an array.

Working great, just throwing the propTypes warning mentioned above 馃憤

What needs to be done to remove this prop-types warning?

In the meantime, I patch this in my own codebase by overriding the default prop types.

For those of you reading this, here is what I do:

import { Route } from "react-router-dom"
import PropTypes from "prop-types"

Route.propTypes = {
  computedMatch: PropTypes.object,
  path: PropTypes.oneOfType([PropTypes.array, PropTypes.string]),
  exact: PropTypes.bool,
  strict: PropTypes.bool,
  sensitive: PropTypes.bool,
  component: PropTypes.func,
  render: PropTypes.func,
  children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
  location: PropTypes.object
}

Hi,

there seems to be an issue with match.params when defining multiple paths for one route with same named params.

Example, using following paths:

const paths = [
    '/:mutation(cs)',
    '/:mutation(cs)-:currency(czk|eur)',
]

Url /cs will have match.params.mutation undefined. It clearly gets overwritten by the 'non matched' mutation from the second path, which is not matched.

This is likely comes from the way pathToRegexp works.

let keys = [];
pathToRegexp(paths, keys);

Will set keys to:

[
  {
    "name": "mutation",
    "prefix": "/",
    "delimiter": "/",
    "optional": false,
    "repeat": false,
    "partial": false,
    "asterisk": false,
    "pattern": "cs"
  },
  {
    "name": "mutation",
    "prefix": "/",
    "delimiter": "/",
    "optional": false,
    "repeat": false,
    "partial": true,
    "asterisk": false,
    "pattern": "cs"
  },
  {
    "name": "currency",
    "prefix": "",
    "delimiter": "/",
    "optional": false,
    "repeat": false,
    "partial": false,
    "asterisk": false,
    "pattern": "czk|eur"
  }
]

The workaround is to name the param in first path differently, and then resolve the params manually.

const paths = [
    '/:mutationA(cs)',
    '/:mutationB(cs)-:currency(czk|eur)',
]

Using version 4.2.2.

Getting same issue as @dorrogeray in one of my projects. The workaround to have different named params for each route is not great. What is the status on this PR? This is highly needed and makes sense to have as it aligns with pathToRegexp expected behavior. When will this go live?

It would be really happy if this feature will be added, but for now I found a solution for my use case.

I made a parameter optional, for use cases like:

  • Route has common path such as /users and /users/create
  • Want to mount once for those compnents

before:

<Route exact path="/users" component={UserList} />
<Route exact path="/users/create" component={UserList>} />

after:

<Route exact path="/users/:action?" component={UserList>} />

before renders twice while after renders once.

Furthermore, UserList.props should be like this:

{
    match: {
        params: {
            action: undefined | string
        }
    }
}

refs:

declare module "react-router" {
  import { RouteProps as RoutePropsOrig } from "@types/react-router";
  import * as React from "react";
  export * from "@types/react-router";

  export type RouteProps = Omit<RoutePropsOrig, "path"> & {
    path: string[] | string;
  };

  export class Route extends React.Component<RouteProps, any> {}
}
// @ts-ignore
Route.propTypes.path = any;

solves the problem :-)

Closed by #5889.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

winkler1 picture winkler1  路  3Comments

sarbbottam picture sarbbottam  路  3Comments

jzimmek picture jzimmek  路  3Comments

davetgreen picture davetgreen  路  3Comments

andrewpillar picture andrewpillar  路  3Comments