React Router Redux always show first route - javascript

React router redux always show the first route. No matter which url i entered, it will render the first route.
Index.js file
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
App.js file
export default function App() {
return (
<Switch>
<Route to="/" component={Dashboard} key={1} />;
<Route to="/icons" component={Icons} key={2} />;
</Switch>
);
}

just add exact={true} to Route, default exact is set to false, just take a look here.
<Route exact path="/" component={Dashboard} key={1} />;

When you make use Switch, you need to add the Routes, whose paths are prefixes to other Routes at the end since Switch matches and renders the first route that matched.
export default function App() {
return (
<Switch>
<Route to="/icons" component={Icons} key={2} />
<Route to="/" component={Dashboard} key={1} />
</Switch>
);
}
And you don't need ; at the end of JSX statements

This is because of the bad route configuration in your example. You need to add exact prop to the first route.
Example:
<Switch>
<Route exact to="/" component={Dashboard} />;
<Route to="/icons" component={Icons} />;
</Switch>
If you don't add exact to the "/" route, then it will always be matched, because every other route also has the / as its part.
My suggestion is to define all routes as exact by default, and only set non-exact routes when required such as:
<Switch>
<Route exact to="/" component={Dashboard} key={1} />;
<Route exact to="/icons" component={Icons} key={2} />;
<Route to="/icons/:iconId" component={IconDetails} key={3} />;
</Switch>

Related

React router v6, group routes by feature

I am using React router v6.
THE PROBLEM:
my App.tsx is very big as it includes routes for all of the application:
Ex.
...
<Route path="products/" element={<ProductsList />} />
<Route path="products/:slug" element={<ProductView />} />
... about 300 lines
I would like to group these routes by feature so that I end up having something like this:
...
<Route path="admin" element={<AdminRoutes />} />
<Route path="products" element={<ProductsRoute />} />
...
it would look cleaner and easier to read.
So far I have created something like this for the Admin section:
export const AdminRoutes = (): any => {
return (
<Routes>
<Route path="admin" element={<Admin />}>
</Routes>
)}
and I have imported it like this inside App.tsx:
...
<Route element={<AdminRoutes />} path="admin" />
...
I am expecting to see the <Admin /> component (defined in AdminRoutes), although I don't get any errors the screen is blank.
export const AdminRoutes = (): any => {
return (
<Routes>
<Route path="admin" element={<Admin />}>
</Routes>
)}
Since you're using relative paths, the actual url that this will match is /admin/admin, one comes from the top level route in App, and another from here. Assuming you wanted this to only match "/admin", you can instead do:
<Route path="*" element={<Admin />}/> // Matches /admin
<Route path="dashboard" element={<Dashboard/>}/> // Matches /admin/dashboard
Or you could use an absolute path:
<Route path="/admin" element={<Admin />}/>
<Route path="/admin/dashboard" element={<Dashboard/>}

How do i make navbar disappear in some pages

function App() {
return (
<BrowserRouter>
<Navlinks />
<Routes>
<Route
render={({ location }) =>
location.pathname !== "/" ? <Navlinks /> : true
}
/>
<Route path="SignUp" element={<Signup />} />
<Route path="/" element={<Home></Home>} />
<Route path="Lorem" element={<Lorem />} />
<Route path="AboutUs" element={<AboutUs />} />
</Routes>
</BrowserRouter>
);
}
/* <Route index element={<Home funcNav={setShowNav} />} />; */
// props.funcNav(false);
export default App;
You can add an if statement, and use the location path function, if the pathname is "bla" for example, you can print the navbar, or add a div containing the navbar, but with a hidden visibility.
you can use to get the path.
import { useLocation } from "react-router-dom";
let location = useLocation();
After that, you just have to check where you want to display it and where you don't.
you can create an array like this.
['path1', 'path2', 'path3'].includes(location.pathname) && ...

How to add ```Context``` with routes set up?

I want to add the searchContext context in my App.js so that my Navbar an Results components have access to the variables in it. How would I do this with my routes set up? I tried to just add with with them but that didn't work. This is the code.
<Router>
// Where does <searchContext.Provider> go?
<Navbar></Navbar>
<Routes>
<Route exact path='/' element={<Home />} />
<Route path='/results'>
<Route path='/results/:value' element={<Results />} />
{/*<Route path='/results/:value/:slot' element={<Slot />}*/}
</Route>
// Another route that has nothing to do with searchContext
</Routes>
</Router>
Edit: Added "// Another route that has nothing to do with searchContext"
if i were you i would just wrap the all thing with the provider as long as its not to heavy.
Hellow, this goes with general understanding of context Api,
now the structure of your folders is your choice but i'll be very brief here
//on your context file searchContext.js
import {useState,createContext} from 'react';
export const SearchContext = createContext(null);
export const ContextProvider = props => {
const [search,setSearch] = useState(null);
return <SearchContext.Provider value = {{search,setSearch}}>
{children>
</SearchContext.Provider>
}
//now on your route.js
import { ContextProvider} from '../your/path/file';
....
<Router>
// Where does <searchContext.Provider> go?
<ContextProvider>
<Navbar></Navbar>
<Routes>
<Route exact path='/' element={<Home />} />
<Route path='/results'>
<Route path='/results/:value' element={<Results />} />
{/*<Route path='/results/:value/:slot' element={<Slot />}*/}
</Route>
// Another route that has nothing to do with searchContext
</Routes>
</ContextProvider>
</Router>

React return Outlet component when I use render in route

I am trying to use react-router with props id but it gave me this info:
Matched leaf route at location "/some-12" does not have an element. This means it will render an <Outlet /> with a null value by default resulting in an "empty" page.
I'm using "react-router-dom": "6" and "react": "^17.0.2"
//example Routes
import {Route, Routes } from "react-router-dom";
function App()
return(
<>
<Routes>
<Route path="/about" element={<About />}/>
<Route exec={true} path="/something" element={<Something/>}/>
<Route exact={true} path="/something-:id"
render={(props) => {
<Some id={props.match.params.id} />;}}
/>
<Route path="/contact" element={<Contact />}/>
</Routes>
</>```
//example Some
export default function Some({ id }) {
return(
<>
<p>Some with id: {id}
</>
)}
Where I did mistakes?
In react-router-dom version 6 the Route components render all the routed components on the element prop and there are no longer any route props, i.e. no history, location, or match.
Render the Some component on the element prop and use the useParams hook to access the id route match param. If path="/something-:id" doesn't work then try making the id its own path segment, i.e. path="/something/:id".
function App()
return(
<>
<Routes>
<Route path="/about" element={<About />}/>
<Route path="/something" element={<Something/>}/>
<Route path="/something-:id" element={<Some />} />
<Route path="/contact" element={<Contact />}/>
</Routes>
</>
);
}
...
import { useParams } from 'react-router-dom';
export default function Some() {
const { id } = useParams();
return(
<>
<p>Some with id: {id}
</>
);
}
It might be that you missed a return statement in your element prop.
<Route exact={true} path="/something-:id"
render={(props) => {
return <Some id={props.match.params.id} />;}}
/>
// or
<Route exact={true} path="/something-:id"
render={(props) => <Some id={props.match.params.id} />;}/>
Note: Upon further research, the render prop has been removed in v6. You should use element instead and fetch the :id as per Drew Reese's answer

React router dom v5 default route doesn't work

I'm using react router dom v5 with material ui, and I have my routes in the following way:
import React from 'react'
import { BrowserRouter, Route, Switch } from 'react-router-dom'
import Layout from '../components/layout'
import Login from '../screens/Login'
import NotFound from '../screens/NotFound'
import routes from './routes'
const DynamicRoutes = () => {
return (
<>
{Object.values(routes).map(({ component, path }) => (
<Route exact path={path} key={path} component={component} />
))}
</>
)
}
const Router = () => {
return (
<BrowserRouter>
<Switch>
<Route exact path="/login" component={Login} />
<Layout>
<DynamicRoutes />
</Layout>
<Route path="*" component={NotFound} />
</Switch>
</BrowserRouter>
)
}
export default Router
I have already tried with <Route component={NotFound} />, and neither worked to me. Can anyone help me? The rest of routes work correctly, but when I type a fake route, doesn't go to the NotFound screen.
That occurs because all children of a <Switch> should be <Route> or <Redirect> elements.
You can check more about it in react-router-dom docs.
So, one solution for your code would be do something like that:
<BrowserRouter>
<Switch>
<Route exact path="/login" component={Login} />
{Object.values(routes).map(({ Component, path }) => (
<Route exact path={path} key={path}>
<Layout>
<Component />
</Layout>
</Route>
))}
<Route path="*" component={NotFound} />
</Switch>
</BrowserRouter>
*For your routes object array, Component property must be with an upper C.
You can check this sample code.

Categories