Accessing params of a wildcard path using react router - reactjs

I'm building a deeply nested component that can be navigated to a lot of different ways, so I'm using a wildcard so I don't have to write out all the possible routes, something like:
<Route path={'**/post/new'}>
<CreatePost {...props} />
</Route>
However, now I need to get and use information from where the user came from in the create post component, so if their paths were:
/en/10249/discussion/13353/thread/24/post/new
/en/10015/discussion/14233/post/new
/fr/10350/link/155/post/new
I would need the params:
/en/:b_Id/discussion/:d_Id/thread/:t_Id/post/new
/en/:b_Id/discussion/:d_Id/post/new
/fr/:b_Id/link/:l_Id/post/new
including en, fr, discussion, thread and link, but because I replaced the params with a wildcard I don't have access to those params anymore. These are just a small subset of path examples that can reach /post/new, and why I needed to replace all routes with a wildcard.
I'm currently thinking of parsing the URL by splitting it by / and reading relevant data that way, but I'm looking if there are better alternative approaches.
Is there a way I can write this where I don't need to type out every possible route, while still splitting up the path into separate params?

react-router automatically includes path parameters in the component props.
In your <CreatePost> component, use:
this.props.match.params.d_Id
and so on.
For more info, see this question.

Related

Is it possible to hide secret URL paths when using React Router?

I'm new to React, and have a n00b question and Googling hasn't turned up any good answers, maybe someone here knows:
With React Router or any kind of declarative routing, how do you "hide" private URLs that you don't want every user to know about? Or, if you just want to prevent someone from being able to easily enumerate all valid URLs?
Code splitting doesn't solve this (really) because the user is told what to request to get the rest of the information: I suppose you could put that URL behind authentication or some kind of restriction to prevent public access to it, but won't that cause the JS fetching the code-split import to receive an error, causing that error to bubble up and cause unintended failure behavior?
Edited to add:
The crux of my issue is wanting to essentially do <Route path="/:path"> where :path matches the entire URL path (e.g., could be foo/bar/baz) instead of just the first "part" (e.g., foo) for a URL like https://example.com/foo/bar/baz for example.
I could use <Route path="*"> and do my own URL parsing, but what if I don't want that route to actually handle the request? How do I signal "nope, I don't want this request, fall-through to the next matching Route"?
You can check if the user is authorized to see these routes and then show or hide them.
<Route path="/cities" component={City} />
<Route path="/courses" component={Courses} />
{user.hasPermission && (
<Route path="/secret" component={VerySecretPage} />
)}
If you want to go further, you can create a custom guarded route as described in this blog post.

ReactRouter: Capture part of path and specify a value to match at the same time

I have a path in the format of /somePath/:name where the :name needs to be one of the known strings. I read that the Route component supports an array of URLs to match, so it's easy to generate a list of supported paths, but doing so takes away the convenient of automatically capturing the part of the path.
For example, I currently have a Route component defined like this below.
<Route exact path={SomeKnownNames.map(n => `/somePath/${n}`)} component={SomeRoute} />} />
This should work, but I cannot access the value in props.match.params in the Route component anymore. Is there a way to achieve this without manually parsing the URL?
Let me add that I do NOT want to match if the value of :name is not in the known strings.
I'm using react-router-dom v5.
Apparently, this works:
<Route exact path={SomeKnownNames.map(n => `/somePath/:name(${n})`)} component={SomeRoute} />} />
i.e. If you do /somePath/:name(foo), then it matches /somePath/foo, and foo is captured in props.match.params.name in the route component.
Have you tried doing this:
path={SomeKnownNames.map(n => `/somePath/:${n}`)}
Adding the : allows the names to be treated as params. Try it out, let me know if that is unrelated. I may need more information to better answer your question.
Also, try to use the useParams() hook from React Router. What does it show in your component?
Update: path-to-regexp was removed from React V6, so this answer is obsolete.
React Router uses the path-to-regexp library, which allows you to provide your own regex for a parameter. See https://github.com/pillarjs/path-to-regexp/tree/v1.7.0#custom-match-parameters.
For example, if you want to match /somePath/foo, /somePath/bar, and /somePath/baz, and have match.params contain myParam: "foo", myParam: "bar", or myParam: "baz", use this pattern:
<Route
exact
path="/somePath/:myParam(foo|bar|baz)"
component={SomeRoute}
/>

how to use react-router for dynamic url

I am building extremely stretchable react app and I am using SSR fro SEO.
but I don't know how to handle URL
Like: user can directly land on this URL, domian.com/delhi/cardiologist
In the backend, I have a system of identifying the components for URL, which is for this case is "Speciality" component in "Location: component
I can't go like this
<Rout path={"delhi"}>
<Location/>
</Route>
cause for this case it's Delhi. but for another user, it will be a different city name, I want to reflect the different city in URL but to render same component due best SEO.
SEO is heart of my app.
I am literally new to this kind of things.
please guide me.
I would recommend adding some structure to the path that makes it easier for you to find the location, say:
<Route path='/search/:city/:specialty' component={Specialty} />
So this would match domian.com/search/delhi/cardiologist. You can customize it to whatever makes sense, it could even be a short letter like just /go/ if you are concerned about URL length because of SEO.
Then, inside the Specialty component, you can use match.params.city and match.params.specialty to get the parameters that you are looking for:
function Specialty({ match }) {
const { city, specialty } = match.params;
return (
<p>Search for {specialty} in the city of {city}</p>
);
}
You could still implement a catch-all route using the path that you want:
<Route path='/:city/:specialty' component={Specialty} />
However, that would require always setting the route at the end, so that it only lands on your <Specialty /> component if it doesn't match any other path that you have.

react router v4 about how to match two url with one route and one component

Sorry, my english is not good enough.
Version
4.1.1
I want to match two url with one route and one component.
just like below:
http://host:port/test/orders/id-1
http://host:port/test/products/id-1
How can I write the path for Route?
Thanks.
You can make use of url path parameters to specify multiple paths matching the same route.
In your case the Route will look like
<Route path = "/test/:param/id-1" component={MyComponent}/>
In case you only want to match the /orders/ids-1 and /products/id-1, then you can make use of regex in the path param. react-router makes use of a path that path-to-regexp understands,
The relevant documentation of it is there with the react-router documentation
So you can use
<Route path = "/test/(orders|products)/id-1" component={MyComponent}/>

Redirect react-router-redux push within component lifecycle

So I have a localised site, and need to redirect routes in certain cases. For example, if a user had their UI set to Spanish, and went to mysite.com/about, they would need to be redirected to mysite.com/es/about.
So basically, the routes are duplicated via <Route> components from react-router:
{Object.values(UILanguages).map(locale => {
return (
<Route path={`${locale.basepath}`} key={locale.basepath} locale={locale} component={App} status={200}>
...routes go here
</Route>
)
})}
It would be simple enough to check within the componentWillMount lifecycle method of <App> to find out if I'm on the wrong <Route> component, but then I would have to prepend every single link in my application, which I don't want to do. Instead, I would like dynamic redirecting for foreign languages, as displayed in the first paragraph.
How is this possible?
Use the react router hooks instead it will be cleaner (smaller components) and simpler than using the component lifecycle.
https://github.com/ReactTraining/react-router/blob/master/docs/API.md#onenternextstate-replace-callback
in your case you need to use all 3 arguments because the first one is the next state the second is the redirection you want to make and the third is a callback to call when you are done testing values.
i can give you an exemple about how to make this but i don't really know how your app is structured so instead check this link , it helped me a lot:
https://www.youtube.com/watch?v=JicUNpwLzLY&t=359s
hope this helps!
ps: in some cases you need to define the onChange hook too example : pagination...

Resources