Reputation: 876
I have something like this:
<Route path={["/","/search"]} component={MyComponent} />
I want to add exact
keyword to the "/"
path, but not to the "/search"
path. How can I achieve that ?
Upvotes: 0
Views: 219
Reputation: 85012
The solution is to just have two routes, one of them exact, one of them not. In the comments you expressed concern that that would cause it to unmount and remount, but that's not the case if you're using the same type of components.
If you'd just like a demo to prove it, here's a code sandbox i made. It has 2 routes that show MyComponent, and a third one that shows something else. Unmounting only happens when going to the third one; you can bounce between the two first ones and keep the component mounted, as you can tell because its state remains intact:
https://codesandbox.io/s/nostalgic-jennings-fqi44?file=/src/App.js:274-282
For an explanation of why this works, the short version is that since the component types are unchanged from one render to the next, react's diffing algorithm thinks they're the same element, and so it does not unmount/remount them.
The long version requires us to step through how react renders this kind of thing. Say i render the following:
const SomeCoponent = () => {
return (
<Switch>
<Route path="/search" component={MyComponent} />
<Route path="/somethingElse" component={SomethingElse} />
<Route path="/" exact component={MyComponent} />
</Switch>
)
}
Let's assume this is our app's first render and the url is currently "/". React starts by calling SomeComponent, and gets a return value of a Switch, with a child prop of 3 Routes.
Next, it repeats the process for the children. It renders Switch, and Switch's render method is set up to inspect its children for Routes, and discard any that don't match. Switch's render method thus returns exactly one Route. So now React sees a tree of SomeComponent, with a single Route as its child.
Then it repeats it for switch's children, which have now been whittled down to a single Route. That Route will see that the route matches (a foregone conclusion since switch already did that check), and so Route's render method returns a MyComponent. And again we continue down the tree, building out whatever MyComponent is made of.
Once react has gone through the entire tree, it now has the full virtual dom. Since this is the first render, there's no previous virtual dom to reconcile with and all of this gets pushed out to the real dom.
Now we get to our second render, and the url is "/search". It renders SomeComponent, and gets Switch + the 3 Routes. It renders Switch and gets back a single Route. You and i may think of the route as being "different", but react isn't even attempting to figure out what's different at this point. Then the Route renders, and produces a MyComponent.
Now that rendering is done, it's time to reconcile the virtual dom with the previous dom to see what changed. Looking just at the component types, the first render returned a tree arranged like this:
Switch
Route
MyComponent
// ... etc
The second time, the tree looked like this:
Switch
Route
MyComponent
// ... etc
Identical! The props may be different, but the component types are unchanged. And since component types and keys are the things that react uses to tell whether it needs to create a new element or modify an existing one, it just thinks it needs to modify the existing one. So no unmounting happens.
Upvotes: 1
Reputation: 23
You can't pass array of strings for path as it looks for given argument. when you add "exact" keyword while calling Route, then it looks for identical one given as argument for path.
Something like this should work
<Route exact path="/" component={Home} />
<Route path="/search" component={MyComponent} />
Upvotes: 0
Reputation: 48
Why not just add additional route with the "exact" ?
If you are iterating over it, just check that the route is equal to "/" then add "exact".
Is there any reason, as to why you are not considering these additional ways, if so, let us know, and we will try to assist you further.
Upvotes: 1