Make splat optional in react-router route - javascript

So currently, I want to have a route where it could be any enumeration of ids (kind of like a file browser). It looks like this:
<Route path="/browser">
<IndexRoute component={FileBrowser} />
<Route path=":id">
<IndexRoute component={HardDriveBrowser} />
<Route path="folders/**/:folderId" component={FolderContents} />
</Route>
</Route>
However, if I visit a route such as /browser/1/folders/2, it does not match. I think it is expecting the splat.
Is there a way to specify the splat as optional, or have it default to an empty string?

In react-router v4, simply put ? at the end to make the parameter optional. In react-router v2, you use parenthesis to make a parameter optional. ex: (:folderId) would make that optional.

Related

How to remove trailing in url (React) [duplicate]

I would like to understand better how the useNavigate works as I'm not really understanding the pattern.
This is my Routes
<BrowserRouter>
<Routes>
<Route path="/" element={<Homepage />} />
</Routes>
<Routes>
<Route path="/questionaire" element={<Questionaire />} />
<Route path="questionaire/1" element={<Question1 />} />
<Route path="questionaire/2" element={<Question1 />} />
</Routes>
</BrowserRouter>
On the Questionaire page I use navigate("1") and it goes into the path "/questionaire/1" -
Nice!
Now on question1 I want to go into "/questionaire/2":
navigate("2") - leads me into /questionaire/1/2
navigate("/2") - leads me into /2
navigate("questionare/2") - leads me into /questionaire/1/questionaire/2
How do I make an increment so every question just adds ++
How do I go from questionaire/5 into questionaire/2 using navigate?
I'm using navigate in buttons, should I use LINK? with a button nested in it? Why?
EDIT: doesn't necessarily have to increment the value, but just replace the current number with the one I want - ex question/1 to question/2 or from question/5 to question/3
What you are asking about is the fundamental difference between absolute and relative routing. In react-router-dom#6 the only thing that differentiates relative links and routes from absolute links and routes is the leading "/" character.
Absolute links and routes:
Begin with a leading "/" character, i.e. "/root/segment1/segment2"
Replace the entire path
// "/root/segment1"
navigate("/root/otherPath");
// "/root/otherPage"
Relative links and routes:
Do not begin with a leading "/" character, i.e. "segment2"
Append to the current path
// "/root/segment1"
navigate("otherPath");
// "/root/segment1/otherPage"
...
// "/root/segment1"
navigate("../otherPath");
// "/root/otherPage"
I suggest the following route refactor:
All sibling routes can be wrapped and rendered by a single Routes component.
Use layout and index routes to help manage/organize nested routes.
Code
<BrowserRouter>
<Routes>
<Route path="/" element={<Homepage />} />
<Route path="/questionaire">
<Route index element={<Questionaire />} /> // "/questionaire"
<Route path="1" element={<Question1 />} /> // "/questionaire/1"
<Route path="2" element={<Question2 />} /> // "/questionaire/2"
...
<Route path="<N>" element={<QuestionN />} /> // "/questionaire/<N>"
</Route>
</Routes>
</BrowserRouter>
Use absolute paths to navigate from to the parent path or from question to question:
navigate("/questionaire"); // to parent
navigate("/questionaire/1"); // to question #
navigate("/questionaire/2");
navigate("/questionaire/N");
Use relative paths from the parent layout route on path="/questionaire":
navigate(".."); // to parent
navigate("../1"); // to question #
navigate("../2");
navigate("../N");
Notice here that we can use ".." to navigate relatively to the parent route. This is useful to navigate along sibling components.
as i know. (i am noob)
On the Questionaire page I use navigate("1") and it goes into the path "/questionaire/1" - Nice! Now on question1 I want to go into "/questionaire/2": navigate("2") - leads me into /questionaire/1/2
When you use just a number or string, useNav just adding it with / after current path. If you instead of number 2 write 'hi' it navigate you to /hi.
navigate("/2") - leads me into /2.
Its because you wrote absolute path, if before your string in useNav you will add "/", then its meaning "yourhost"+"your string".
example:
Your host is localhost:3000. If you entered '/test' in useNav it will be localhost:3000/test. Or you want add this "/test/2/3" - then it will be localhost:3000/test/2/3.
navigate("questionare/2") - leads me into /questionaire/1/questionaire/2
as i said if you have just string and before it you didnt add /, then its just added after your current path.
Answering you second question:
How do I make an increment so every question just adds ++ How do I go
from questionaire/5 into questionaire/2 using navigate?
navigate("questionare/2") - leads me into
/questionaire/1/questionaire/2
You can do this using absolute path (e.g: '/questionaire/2') or relative path (e.g: '2'), you can either do this using a Link or programmatically using a useNavigate hook.
const navigate = useNavigate()
const handleClick = () => {
navigate('2')
//or
navigate('/questionaire/2')
}
Your current code is using relative path + adding entire path, which leads to duplicated path as you mentioned.

React router path: making optional value inside path

Consider the following two react route paths:
/site/my/photos/:id
/site/photos/:id
I would like the 'my' inside first path to be optional.
How can I make it optional (probably something to do with ? symbol), and how can I then retrieve if the my is present or not in the URL?
You can pass an array of paths to the Route from react-router-dom, for example:
<Route path={["/site/my/photos/:id", "/site/photos/:id"]} component={MyComponent} />
i think you should define two routes with same component like below :
<Route path="/site/my/photos/:id" component={MyComponent} />
<Route path="/site/photos/:id" component={MyComponent} />

React Router Switch Component Matches

In the react router docs here it says:
Consider this code:
<Route path="/about" component={About}/>
<Route path="/:user" component={User}/>
<Route component={NoMatch}/>
If the URL is /about, then <About>, <User>, and <NoMatch> will all render because they all match the path.
How do they all match the path /about? I can't see why this would be true, unless a user had the username about. What am I missing?
The Line
<Route path="/:user" component={User}/>
means that everything after / will be passed into this.props.params.user variable of component and User component would be rendered.
The matching rule only cares if the path given matches your path= pattern, it doesn't care if the resource actually exists. If I get path starting with / the and there is a text following the variable, the text will be parsed as Route Parameter user and User component will be rendered and that's it. So yes, this.props.params.user will have value of "about" in this case, but how you handle the variable and what would you display in case user such name is not found is entirely up to you.
I think they are just trying to say that in case that you have more patterns that would normally get matched all at once, you should use <Switch> component so only the first match would actually render.
So e.g. when used <Switch>:
A) and the path is /about, rule
<Route path="/about" component={About}/>
would get matched and About component would get rendered and no more evaluation are done.
B) if the path is /something, rule
<Route path="/about" component={About}/>
won't get matched, but rule:
<Route path="/:user" component={User}/>
would get matched, and User component would be rendered with something as this.props.params.user param and no more evaluation are done.
C) If the path is / the rules
<Route path="/about" component={About}/>
<Route path="/:user" component={User}/>
won't get matched but
<Route component={NoMatch}/>
will and NoMatch component would get rendered.
On contrary when not using <Switch>, if your path is /about:
<Route path="/about" component={About}/>
Would get matched, because this rule matches all routes which paths are equal to /about.
<Route path="/:user" component={User}/>
Would also get matched because this rule matches all routes which start with / and there is a text following.
<Route component={NoMatch}/>
Would too get matched because this rule doesn't care about path at all, it gets always matched.
As they're not contained within a <switch>...</switch> element, they're all evaluated, and evaluated independently.
The router has no knowledge of the users in the system - it's only looking for a string match within the path.
Something like:
if (path === '/about') { return 'About' }
if (typeof path === 'String') { return 'User' }
if (true) { return 'noMatch' }

URL with query string not matching react-router route

Given this React router configuration:
<Router history={browserHistory}>
<Route path="/farm/:type?period=:period" component={Farm} />
<Route path="/pen/:penId" component={Pen} />
<Route path="/pen/:penId/cow/:cowId" component={Cow} />
<Route path="*" component={Farm} />
</Router>
Why is http://localhost:8080/farm/average?period=day only matching the catch-all route and not the first one?
Query string parameters don't need to be included in the <Route> definition.
Changing the route definition to <Route path="/farm/:type" component={Farm} />
solved the problem.
Query string parameters are still available under props.location.query

React Router Param

Is it possible to do this with react router?
<Route path="/:reset_password" component={ResetPassword} />
<Route path="/:create_password" component={CreatePassword}/>
I want use different param with different component. I test above code and it doesn't work. the code above work if I change to this:
<Route path="/something1/:reset_password" component={ResetPassword} />
<Route path="/something2/:create_password" component={CreatePassword}/>
thanks for the help
As #chris said, remove the colons and/or assign dedicated routes. React Router can't differentiate between the two routes you've supplied, as they're technically identical (root path + a dynamic parameter.)

Categories