React Router with Optional Path Parameter

React Router with optional path parameter

The edit you posted was valid for an older version of React-router (v0.13) and doesn't work anymore.



React Router v1, v2 and v3

Since version 1.0.0 you define optional parameters with:

<Route path="to/page(/:pathParam)" component={MyPage} />

and for multiple optional parameters:

<Route path="to/page(/:pathParam1)(/:pathParam2)" component={MyPage} />

You use parenthesis ( ) to wrap the optional parts of route, including the leading slash (/). Check out the Route Matching Guide page of the official documentation.

Note: The :paramName parameter matches a URL segment up to the next /, ?, or #. For more about paths and params specifically, read more here.



React Router v4 and above

React Router v4 is fundamentally different than v1-v3, and optional path parameters aren't explicitly defined in the official documentation either.

Instead, you are instructed to define a path parameter that path-to-regexp understands. This allows for much greater flexibility in defining your paths, such as repeating patterns, wildcards, etc. So to define a parameter as optional you add a trailing question-mark (?).

As such, to define an optional parameter, you do:

<Route path="/to/page/:pathParam?" component={MyPage} />

and for multiple optional parameters:

<Route path="/to/page/:pathParam1?/:pathParam2?" component={MyPage} />

Note: React Router v4 is incompatible with react-router-relay (read more here). Use version v3 or earlier (v2 recommended) instead.

optional /id?/ parameter in React Route path not working

It depends on which version of the react router you're using.

For V1, V2 and V3 optional parameters can be defined as:

<Route path='/cart(/:id)' element={< CartScreen />} exact/>

For React Router V4,V5 you can use:

<Route path='/cart/:id?' element={< CartScreen />} exact/> 

As for React Router V6, it no longer supports optional routes but instead opts for nested Routes.

<Route path="/page/:friendlyName">
<Route path=":sort" element={<Page />} />
<Route path="" element={<Page />} />
</Route>

Official docs for changes going from V5 to V6. See the relative links section for more information.

React Router 4 with optional path AND optional parameter

Sadly there doesn't seem to be a way to do this. The ideal way would be to create two separate Routes for your purpose.

<Route exact path="/tasks/:id" component={...} />
<Route exact path="/tasks/:id/notification/:notificationId" component={...} />

If you really must only declare one Route, you could use a custom regex rule (the part that is wrapped in parentheses after the parameter name declaration):

<Route exact path="/tasks/:id/:notificationId(notification/\d+)?" component={...} />

However!! - note that the notificationId parameter will include the substring "notification". For example, if you have:

tasks/123/notification/456

You will have a taskId of "123" and notificationId of "notification/456" (the whole string)!

That said, the route above will match the following paths:

  • tasks/123
  • tasks/123/notification/456

but not:

  • tasks/123/notification
  • tasks/123/notification/abc
  • tasks/123/456

etc...


TL;DR - You probably want to use two individual routes as shown in the first example above.

Optional Path React Router 4

I can do the following to match both paths:

<Route exact path="/account/(orders)?" component={Orders} />

Add optional query parameters to a dynamic path using React Router

react-router-dom doesn't use the queryString for route path matching. Remove the queryString part from the route path prop. Access the query params in the component via the useSearchParams hook.

<Route path=":id" element={<User/>} />

...

import { useSearchParams } from 'react-router-dom';

const User = () => {
const [searchParams] = useSearchParams();

const makeYear = searchParams.get("makeYear");
// handle logic based on makeYear

...
};

Multiple Optional Params in React Router

UPDATED

This is an updated answer based on a better understanding of the requirements. It appears that you want hello and goodbye to actually be names of URL parameters so that you can grab them in the rendered component.

You have come pretty close to accomplishing this already.

In my example, I will use prameter name var1 (instead of hello or goodbye) so that by accessing your app using /project/1234/hello you will get {context: "1234", var1: "hello"} and this URI /project/1234/goodbye will yield {context: "1234", var1: "goodbye"}

All you need is this Route:

<Route
exact
path={["/project/:context", "/project/:context/:var1"]}
component={Project}
/>

Then in the rendered component, you can access the URL params like so:

props.match.params

Similarly, this won't work, because using an array, /project/1234/goodbye will always match /project/1234 first, and therefore I won't get any of the params passed through using the useParams() hook that react-router provides.

You are absolutely correct, unless you use the exact param.

Here is a Sandbox: https://codesandbox.io/s/react-router-5-forked-1jjwt?file=/src/index.js



Related Topics



Leave a reply



Submit