Different Nav based on route react router - javascript

Hello all I did use search but I couldnt find anything that solved this problem.
I need two navbars one for most pages and one for a specific set of routes
code
<BrowserRouter>
<Header />
<Switch>
<Route exact path="/" component={() => <div>home</div>} />
<Route exact path="/services" component={() => <div>services</div>} />
</Switch>
</BrowserRouter>
I need something that would say render all routes except /services/* because /services/* has different
I thought about changing things inside Header but there will be too many changes it would be easier to have different component.

You could set up a condition inside your path. I haven't tested this, but something in that nature could help you combine and separate certain routes.
<BrowserRouter>
<Header />
<Switch>
<Route exact path={"/allComponents" || "/"} component={() => <div>home</div>} />
<Route exact path="/services" component={() => <div>services</div>} />
</Switch>
</BrowserRouter>

Related

React Router v6 index routes giving trailing slash error

I'm using react router v6 and I'm having trouble with correctly using index routes. I have the following top level routes which all work fine except navigating to "/".
<Routes>
<Route path="/" element={<DefaultPage />}>
<Route path="profile/*" element={<UserProfile account={true} />} />
<Route path="register/*" element={<UserProfile account={true} register={true} />} />
<Route path="user/:username/profile" element={<UserProfile />} />
{/*<Route path="account*" element={"Account"} />*/}
<Route path="feed/:slug/*" element={<StreamPage type="feed" />} />
<Route path="user/:slug/*" element={<StreamPage type="user" />} />
<Route path="post/edit" element={<PostEditorPage />} />
<Route path="post/edit/:id" element={<PostEditorPage />} />
<Route path="publication/edit" element={<PubEditorPage />} />
<Route path="publication/edit/:slug" element={<PubEditorPage />} />
<Route path="publication/:id" element={<PubPage />} />
<Route index element={<StreamPage index={true} />} />
</Route>
</Routes>
When I go to the root url <StreamPage index={true} /> renders as expected using the Outlet specified in DefaultPage but I get the following warning:
You rendered descendant <Routes> (or called useRoutes()) at "/" (under <Route path="">) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render.
Please change the parent <Route path=""> to <Route path="/*">."
This doesn't seem to happen with any of the other routes and when index is true StreamPage doesn't render any child routes so the problem has to be here but my code seems to resemble the examples from the docs pretty closely so I can't figure out what I'm doing wrong. Thoughts?
Note that the warning persists if I change the top line to
<Route path="/*" element={<DefaultPage />}>
For completness here is the relevant part of StreamPage
EDIT: Added the top Routes section thanks to help from comments identifying that there was a missing piece to generate the warning.
<Routes>
<Route index element={<StreamSidebar/> } />
<Route path="post/:subslug/*" element={<Sidebar/> }/>
</Routes>
{index && <Stream stream={stream} index={index} />}
{!index &&
<Routes>
<Route index element={<Stream stream={stream} index={index} />}/>
<Route path="post/:subslug/*" element={<PostPage stream={stream} />}/>
</Routes>}
(I can include the full thing if necessary but this is the only part with routes in it and even those shouldn't render when index is true)
}
#Drew Reese's responses answered the primary issue I was having with this code so I'm marking this as answered. What rule this code violates seemed different enough that I created a separate question that gives a really minimal example of how sibling nested index routes generate the warning and avoids all the confusion about what the heck all this other stuff is doing.
its maybe for use of /* in your route and if you will be deep in path of your route may cause of problem

How to configure the Routes in Sidebar navigation after Login page in React?

I am designing a users dashboard in React, wherein User logs in and navigate to his dashboard with other links such as Archived, Profile and Settings. My Login and then Navigating to HomePage is working fine.
I have designed the Dashboard, Archived, Profile and Settings Page Links in Sidebar. Now when I am navigating to the Links. It takes me to a new URL path and my Sidebar disappears. I want my sidebar to still appear on all pages as long as I am logged in.
Below is my App.js where I have designed the upper level route:
return (
<div>
<Router history={history}>
<Switch>
<PrivateRoute exact path="/" component={HomePage} />
<Route path="/login" component={LoginPage} />
<Route path="/register" component={RegisterPage} />
<Redirect from="*" to="/" />
</Switch>
</Router>
</div>
);
Once User is on HomePage, I need the dashboard and other links to show. and when User clicks on any Sidebar link, Sidebar should still be there while the other page opens. So I added the inner Routes to the HomePage.jsx like this:
return (
<div>
<Router history={history}>
<Sidebar />
<Switch>
<Route path="/" component={Dashboard} />
<Route path="/archived" component={ArchivedPage} />
<Route path="/profile" component={ProfilePage} />
<Route path="/settings" component={SettingsPage} />
{/* <Redirect from="*" to="/" /> */}
</Switch>
</Router>
</div>
);
But it doesn't work. Can anyone please help me understanding if this is correct. or how can I achieve the required result.
Please let me know if you need any other details.
Thank you.
Issue
The issue is that you are exactly matching "/" to render HomePage, but then as soon as the path is any deeper, like "/archived", it no longer exactly matches and HomePage is unmounted.
You should not render a Router within another Router, you need only one router per app to provide the routing context.
Solution
Remove the inner router (and any other nested routers!!). Remove the exact prop on the "/" path and reorder the routes to specify the more specific paths before less specific paths so the Switch can actually do its job and match and render the appropriate route.
App
Reorder the more specific "/login" and "/register" paths to be matched prior to the less specific "/" path. If you had, for example, a "/login/google" path, this is more specific than "/login" and would be ordered earlier.
return (
<div>
<Router history={history}>
<Switch>
<Route path="/login" component={LoginPage} />
<Route path="/register" component={RegisterPage} />
<PrivateRoute path="/" component={HomePage} />
<Redirect to="/" />
</Switch>
</Router>
</div>
);
HomePage
Move the Dashboard to the last route position so if no other route above it is matched and returned then the dashboard is matched and rendered.
return (
<div>
<Sidebar />
<Switch>
<Route path="/archived" component={ArchivedPage} />
<Route path="/profile" component={ProfilePage} />
<Route path="/settings" component={SettingsPage} />
<Route component={Dashboard} />
</Switch>
</div>
);
in first place your doing something wrong you cant put a Router inside a Router,
you haver a Router in app then inside a component that is inside of app you have another Router thats a problem i dont know if that solves your problem but try it just delete Router in homepage

React Router: How to render element on all routes, except one?

I have HTML structure like this:
<body>
<nav>
<!--navigation elements -->
</nav>
<div className='main'>
<!--other elements -->
</div>
<div className='container'></div>
</body>
And routing defined like this:
<Router>
<Fragment>
<Navbar />
<Route exact path="/" component={Landing} />
<div className="container">
<Alert />
<Switch>
<Route exact path="/register" component={Register} />
<Route exact path="/login" component={Login} />
<Route exact path="/profiles" component={Profiles} />
</Switch>
</div>
</Fragment>
</Router>
The "container" element is present on all routes however I do not want it to be rendered on the "/" route.
How can I stop <div className="container"> from being rendered on the "/" route? I want it to be rendered on all other routes except of "/".
A solution I found, but don't want to use is to explicitly insert the element with class="container" in each component that is rendered in my <Switch>. Is there a better way?
You should be able to achieve what you require via nested routes and a "no match route".
The idea would be to introduce structure to your routing via nested routes, to restrict rendering of <div className="container"> to non / routes.
To do this, you could extract a component (ie WithContainer) that renders a <Route> for paths; /register, /login and /profiles, inside of the <div className="container">. You would then change your <Switch> to now render two routes for the following route cases;
A <Route/> that renders the Landing component on an exact match of /
A <Route/> that renders your new WithContainer component on no specific route (ie any path that does not exactly match /)
By using the <Switch> in this way, it causes the routing behaviour to render either Landing or WithContainer (but not both) depending on the first matched route. We take advantage of that behaviour to restrict rendering of the WithContainer (and in turn, the <div className="container"> element) for "non /" routes.
In code, this approach could be expressed as:
const WithContainer = () => (
<div className="container">
{ /* Wrap routes in container div */ }
<Route exact path="/register" component={Register} />
<Route exact path="/login" component={Login} />
<Route exact path="/profiles" component={Profiles} />
</div>)
const Main = () => (
<main>
<Switch>
<Route exact path='/' component={Landing}/>
<Route component={ WithContainer } /> {/* No match route */ }
</Switch>
</main>
)
Hope that helps!
With the latest version of React Router, you can provide an array of strings for the path prop so that a specific route renders on multiple matches:
<Route path={['/one', '/two', '/three']} component={SomeComponent} />
Here's a link to the relevant documentation: https://reacttraining.com/react-router/web/api/Route/path-string-string.
If you don't want to create a separate component, you can just do this. You need to keep the inner switch as well, if you want to keep the original functionality.
// parent switch
<Switch>
<Route exact path="/" component={Landing} />
// start route wrap!!!
<Route>
<div className="container">
<Switch>
<Route exact path="/register" component={Register} />
<Route exact path="/login" component={Login} />
<Route exact path="/profiles" component={Profiles} />
</Switch>
</div>
</Route>
// end route wrap!!!
</Switch>
You should think of Routes as of any other UI components. You can nest them arbitrarily.

Multiple entry point in webpack

I want to use multiple entry point for login like '/user/login' & '/admin/login'. I am bit confused about this. Should I use separate files for this, or IS there any way where I can use multiple entry point using the same file? I am using react.js
React Router 4 is a great router for React that allows you to configure paths like this:
<BrowserRouter>
<Switch>
<Route path="/user/login" component={LoginComponent} />
<Route path="/admin/login" component={LoginComponent} />
<Route path="/blueberry/login" component={LoginComponent} />
<Route path="/user/signin" component={LoginComponent} />
<Route path="/admin/signin" component={LoginComponent} />
<Route path="/blueberry/signin" component={LoginComponent} />
</Switch>
</BrowserRouter>
You can also use RegEx to simplify:
<BrowserRouter>
<Switch>
<Route
path="/(user|admin|blueberry)/(login|signin)"
component={LoginComponent} />
</Switch>
</BrowserRouter>

react router v4 route changed but did not render the correct component

I have 2 level of route, the first layer it look like this
<BrowserRouter>
<div>
<AuthRoute></AuthRoute>
<Switch>
<Route path='/dashboard' component={Dashboard} />
</Switch>
</div>
</BrowserRouter>
where in AuthRoute I have a redirect upon componentDidMount
this.props.history.replace(/dashboard/redirected)
The problem is within the dashboard/index which is my 2nd level of route config
<BrowserRouter>
<Switch>
<Route exact path='/dashboard' component={()=><h1>dashboard index</h1>} />
<Route exact path='/dashboard/somewhere' component={()=><h1>somewhere</h1>} />
<Route exact path='/dashboard/redirected' component={() => <h1>redirected</h1>} />
</Switch>
</BrowserRouter>
The route changed to /dashboard/redirect but the component didn't render the correct one if you refresh on says /dashboard/somewhere or /dashboard/
You can see the problem clearer in the demo I setup https://codesandbox.io/s/v0v4qok38l
You only need one <BrowserRouter> in the application - removing it from dashboard/index.js will fix your issue.

Categories

Resources