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' }
Related
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.
Matched leaf route at location "/" does not have an element. This means it will render an with a null value by default resulting in an "empty" page
//App.js File
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
// import ReactDOM from "react-dom";
const App = () => {
return (
<Router >
<Routes>
<Route path="/" component={ Home }></Route>
</Routes>
</Router>
)
}
export default App;
**My any react router related code not working i don't know why it happend when i start insert some route in program so it show this error **
In V6, you can't use the component prop anymore. It was replaced in favor of element:
<Route path="/" element={<Home />}></Route>
More info in the migration doc.
I had the same problem. Replace component with element and it worked.
Replace this:
<Route path="/" component={HomePage} exact />
with this:
<Route path="/" element={<HomePage/>} exact />
I had the same error however my fix was slightly different
I had spelled element wrong.
<Route exact path='/MyGames' elemtent={<MyGames/>}/>
and this was the error it gave me in the browser console
Matched leaf route at location "/MyGames" does not have an element. This means it will render an <Outlet /> with a null value by default resulting in an "empty" page.
Very simple:
use element instead of component
wrap the your component like this: {<Home/>} instead of {Home}
<Route path="/" component={ <Home/> } />
in version 6:
component replaced with element and needs to close "</Route>"
<Route exact path="/" element={<AddTutorial />}></Route>
https://reactrouter.com/docs/en/v6/getting-started/overview
This is a common problem if you are using react-router-dom V6
To solve this it's simple
In your code
Replace component with element
Replace {home} with {}
This becomes...
<Route path="/" element={}>
This will definitely solve the problem.
If you're using react-router-dom 6 or above, you may have a routes array that includes parent and child routes. You may then try to open a route such as
/portal
and get this error because that component corresponds to a child route
/:customerid/portal
but you haven't read your routes (and their child routes) closely enough to see that.
I'm trying to use REGEXP to help render a 404 page in a react app using the path. I cannot figure it out.
This is the REGEXP I want; I want to match IF:
The entire path is !== '/' && does not contain the word 'article'.
EDIT: Including code for clarification:
<Switch location={location} key={location.pathname}>
<Route path={["/commentisfree/article/:id", "/commentisfree"]}>
<Opinion />
</Route>
<Route path={["/sport/article/:id", "/sport"]}>
<Sport />
</Route>
<Route path={["/culture/article/:id", "/culture"]}>
<Culture />
</Route>
<Route path={["/lifestyle/article/:id", "/lifestyle"]}>
<Lifestyle />
</Route>
<Route path={["/signup", "/login"]}>
<Account />
</Route>
<Route path={["search/:search", "/search"]}>
<Search />
</Route>
<Route path={/REGEXP[if path !== "/" && path does NOT include the word "article"]/} component={ErrorDefault} />
<Route path={["/article/:id", "/"]}>
<Home />
</Route>
</Switch>
At the bottom you'll see I've had to put the 404 component just above my index route because the 404 is never hit if I use a catch all route, it simply navigates to the index route but maintains the incorrect URL.
For example, entering http://localhost:3000/mistake takes me to the index route. I don't want this as I rely on the urls to render modular components and it doesn't work if the path is incorrect.
So i need to force any non declared paths to a 404 page where i can display a message and a link back to the home page.
Are you using React router?
If so, you could use a catch-all route at the end of the route list, which will render a 404 page, like here: https://reactrouter.com/web/example/no-match
Edited: added link to React router documentation
The following function uses Regular Expression
const checkRegex = (urlString) => {
return (
new RegExp("/").test(urlString) && new RegExp("article").test(urlString)
);
};
You can also use the includes function for this
const checkRegex = (urlString) => {
return (
urlString.includes('article') && urlString.includes('/')
);
};
I am using the same component for three different routes:
<Router>
<Home path="/" />
<Home path="/home" />
</Router>
Is there anyway to combine it, to be like:
<Router>
<Home path=["/home", "/"] />
</Router>
For Reach Router: (https://reach.tech/router/example/)
With the exact sample shown, the only way I can see how to do this(on a single line) is with a wildcard.
To find a way to reproduce this without side effects, we would need to see the entire nav menu.
<Router>
<Home path="/*" />
<Chicken path="chicken">
</Router>
...
const Home = props => {
let urlPath = props["*"]
// URL: "/home"
// urlPath === "home"
// URL/: "/"
// urlPath ===""
}
You could continue with other paths below Home and the router would allow them to process.
Check out the the example using a wildcard and reach router on codesandbox, I wrote!
Note: This is a catch-all, but without parsing a parameter is the only single line solution I saw.
Some DrawBacks include Home rendering instead of '404', etc.
//This could be resolved with an if statement in your render
//It will not produce the intended URL either for /home, and I have not looked into that since it is not part of the question.. but if it matched props[*] I'm sure you could redirect or something.
You can read more about the Route Component for Reach Router.
https://reach.tech/router/api/RouteComponent
I wasn't happy with the wildcard solution from the documentation and #cullen-bond because I had to map many other paths and came up with this solution:
<Router>
{["/home", "/", "/other", "/a-lot-more"].map(page => <Home path={page} />)}
</Router>
Example: https://codesandbox.io/s/reach-router-starter-v1-forked-6f44c?file=/src/index.js
Depending on the situation you're dealing with, <Redirect /> could also make the work.
<Router>
<Redirect from="/" path="/home" noThrow />
<Home path="/home" />
</Router>
You can use a single component for mutiple paths, by using a array of routes.
code example :
import sampleComponent from './sampleComponent'; // single component for mutiple routes
<Router>
<Switch>
{["/pathname_1", "/pathname_2", "/pathname_3", "/pathname_4", "/pathname_5", "/pathname_6"].map(pathname => (<Route exact path={pathname} component={sampleComponent} />) )}
<Switch>
<Router>
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.