Two independent route systems with react-router - reactjs

what I want to do is that my website has admin panel with the following routes /admin/.... and then the normal web would be /...
But the urls come together when I enter / works well but when I enter /admin you see the web menu and the admin menu when you would only have to see the menu of the administrator I leave the demo that performed in CodeSandBox, I hope you can help me.
https://codesandbox.io/s/react-router-admin-users-5wzte
Greetings and thanks.

Wrap your routes in a Switch component. The Switch will return only the first matched route. More info is available here:
https://reacttraining.com/react-router/web/guides/basic-components

The issue is because, your path /admin getting matched with your both Route.
You need to provide an exact prop,
<Route
path="/"
exact //exact prop will help to match exact path
render={userProps => (
<Layout match={userProps.match}>
<h2>Menu Web</h2>
<Route exact path="/" component={Home} /> //Add exact here also otherwise it will get match for path `/contact`
<Route path="/contact" component={Contact} />
</Layout>
)}
/>
Also you need to make use of Switch, which
Renders the first child <Route> or <Redirect> that matches the location.
Just wrap your Route with Switch.

Related

What is the correct way to setup an independent Route that is not a part of App.js in React Router Dom?

I'm trying to create an independent Route (not sure if that's the correct term) at BulletinBoard.js where I can use Link to go to Create Bulletin component.
I'm also trying to create another independent Route at BulletinList.js where I can navigate to Edit Bulletin with their respective IDs.
Before this, I tried using useRouteMatch with path and url, but apparently that wasn't the correct way to do it, now I'm told to use useLocation, it does adds the /createbulletin and /editbulletin/id paths behind the current URL, but it doesn't navigate to the component itself.
I've been cracking my head over this for the past 2 days and I still haven't figured out the correct way to do this.
Here is the codesandbox that I've created for reference.
The reason your code didnt navigate to a different component after the url changed is because you didnt use the exact attribute when declaring the route. So its matching /bulletinboard/anything and then it always renders de BulletinBoard component.
You could define all routes at the App.js file like
<Switch>
<Route path="/" component={Home} exact />
<Route path="/bulletinboard" component={BulletinBoard} exact />
<Route path="/bulletinboard/edit/:id" component={EditBulletinBoard} exact />
<Route path="/infohub" component={InfoHub} exact />
<Route component={NotFound} />
</Switch>
Also, check out the useHistory hook
So at the BulletinBoard.js when the user clicks the link
onClick={() => history.push(`/bulletinboard/edit/${id}`)}
Note that the edit route renders a different component that your codesandbox didn't have yet

React Router: Wrapping some Routes with a component and not directly inside Switch

I'm trying to do something like this
<Switch>
<SomeNavBar>
<Route path="page1">Page 1</Route>
<Route path="page2">Page 2</Route>
<Route path="page3">Page 3</Route>
</SomeNavBar>
<OtherNavBar>
<Route path="admin">Admin Page</Route>
</OtherNavBar>
</Switch>
Where I have wrapper component for a routes that are not the admin page.
However the admin route does not render Admin Page it just renders a blank page. The other routes work fine.
Is there a way to achieve this behavior?
There's a couple of issues with your example not related to the question which you should rectify before anything else.
The first is that the direct children of a Switch must always be a Route or Redirect - it doesn't know what to do with any other element and will just render the first thing it sees (in your case, the SomeNavBar component). The second is that path declarations must be prepended with a slash for the router to build them correctly, so /page1 and /admin for example.
With that out the way, here is a somewhat contrived example of how to get the behaviour you are after. For the pages, we are checking from a list of possible fragments before rendering SomeNavBar and the correct route. Notice also the exact parameter - this is so we don't also match paths that only begin with the specificed fragment, like /page1foo:
<Switch>
<Route exact path={['/page1', '/page2', '/page3']}>
<SomeNavBar>
<Route path="/page1">Page 1</Route>
<Route path="/page2">Page 2</Route>
<Route path="/page3">Page 3</Route>
</SomeNavBar>
</Route>
<Route path="/admin">
<OtherNavBar>
Admin Page
</OtherNavBar>
</Route>
</Switch>

How to display not found page on not define slug ? / React Router DOM

How I can display something like page not found in a define route path, but with not valid slug?
Example:
I have defined route with path /about:
<Switch>
// other routes
<Route path="/about" component={AboutPage} />
<Route component={PageNotFound} />
</Switch>
When I visit link like this :
I got about page component, but I have the wrong slug (or not defined) after route (in my case /about), how to catch that and display not found page in example code above.
Thanks. o/
The reason you still get to the About page is because you're still matching the path. If you only want to go to a route if the path match is exact, you can pass the exact flag to the Route: <Route exact path='/about' component={AboutPage} />
not sure if I understood you fully, but are you aiming to achieve something like in this exact & strict example?
So for localhost:3000/about you'd see the about page, but for localhost:3000/about/sth you'd get redirected to /?

React Router Parameter Under Subpath

I have a React app I'm playing with and using with a star wars API I built locally.
The first two routes work just fine but I don't understand why the third one doesn't work.
My guess is that going to the third route the second component thinks that the work "edit" is the parameter.
Question is, how can I make the third route work as I would like or do I have to take another approach.
I was hoping to have the Edit Episode page be in the same group as the components I use in the "starwars" path.
<Route path="/starwars" exact component={Movies} />
<Route path="/starwars/:id" component={Episode} />
<Route path="/starwars/edit/:id" component={EditEpisode} />
Try adding exact attribute to the second route. It should solve the problem.
<Route path="/starwars" exact component={Movies} />
<Route path="/starwars/:id" exact component={Episode} />
<Route path="/starwars/edit/:id" component={EditEpisode} />
Without exact attribute, all the incoming request to /starwars/{whatever-after-this} matches to the second route and it stops there.
Can you please change the order of the Route and set exact keyword to the /starwars/edit/:id path.
<Route path="/starwars" exact component={Movies} />
<Route exact path="/starwars/edit/:id" component={EditEpisode} />
<Route path="/starwars/:id" component={Episode} />
Hope this will work for you!
Can you check thepublicPath on the output property in your webpack.config file. This should point to the root of your app.
I've been there and this worked for me.
output: {
path: path.resolve('dist'),
publicPath: '/'
}

React Router v4 rendering component twice

Here is my Router Implementation
<BrowserRouter>
<div>
<Route exact path="/" component={ProfilesIndex} />
<Route exact path="/profiles" component={ProfilesIndex} />
<Route exact path="/profiles/new" component={ProfileEditor} />
<Route exact path="/profiles/:id" component={ProfileEditor} />
</div>
</BrowserRouter>
When I am browsing to /profiles/new path, it is rendering the ProfileEditor component twice. For every other route, it is working fine.
Can someone suggest how to fix this problem ?
I found the answer after browsing into multiple sections in Router Docs. Problem was it was matching multiple routes
When user opens /profiles/new it matches two routes
/routes/new
/routes/:id
Because :id is like a wildcard * and it also matches new word so both routes get matched and hence the component gets rendered twice.
The solution is to wrap the routes with Switch if you do not want to match multiple routes.
<BrowserRouter>
<Switch>
<Route exact path="/" component={ProfilesIndex} />
<Route exact path="/profiles" component={ProfilesIndex} />
<Route exact path="/profiles/new" component={ProfileEditor} />
<Route exact path="/profiles/:id" component={ProfileEditor} />
</Switch>
</BrowserRouter>
For anyone coming here from v6+
exact prop no longer exists, the paths are exact by default if they aren't appended a wildcard *
However I was still getting a double render. I ran a prod build and checked and the double render is gone so probably nothing to worry about - sometimes hooks run twice in development mode (I guess that's what's happening internally)
for me, this is because of React.StrictNode which is wrapped arround App component.
it intentionally double render components (only in development) to enforce you, not use side effects on some of your component's
lifecycle events.
the reason behind that is documented here

Resources