I build a website in react with Browserrouting and have the following code & issue
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<BrowserRouter>
<Routes>
<Route path="/" element={<App/>}>
<Route path="/home" element={<Homepage />} />
The Problem I have is when i run the App it opens the "App" and not the actual Homepage.
I tried to fix it by changing change the App to Homepage but it is not working.
In my understanding / needs to be there so the App displays in any other Path and is functioning.
Can some explain me, how i can make the path / still the Homepage without having to type /home to get there?
Thank you !
It appears you are rendering the Homepage in a nested route that is rendering App. In this configuration <Route path="/" element={<App />}> is what is called a Layout Route. App will be rendered when the path is exactly "/" and should render an Outlet component for the nested routes to render their content to.
An issue I see here, and you should have been seeing a react-router-dom invariant error regarding nesting an absolute path within a route rendering on an absolute path. In other words, "/home" is an absolute path and can't be nested under the absolute path "/"; it's not reachable.
If App really is a layout route and you always want it to render then you could remove the path prop from the parent route rendering App, and move Homepage to "/".
<BrowserRouter>
<Routes>
<Route element={<App />}>
<Route path="/" element={<Homepage />} />
</Route>
</Routes>
</BowserRouter>
or convert Homepage into an index route and leave the "/" path on the parent layout route so the relative routing can still work properly and Homepage is rendered on "/".
<BrowserRouter>
<Routes>
<Route path="/" element={<App />}>
<Route index element={<Homepage />} />
</Route>
</Routes>
</BowserRouter>
I should point out that this is a slightly abnormal configuration. Typically the App component would render the Routes and Route components instead of an Outlet and it's assumed to all render on "/" by default. The Homepage component would then be rendered on path="/".
Example:
<BrowserRouter>
<App />
</BowserRouter>
...
const App = () => {
.... app logic ....
return (
<Routes>
<Route path="/" element={<Homepage />} />
</Routes>
);
};
There is OFC, the chance here that you didn't intend to nest these routes and want them to be matched and rendered independently. In this case the solution is to just unnest the Homepage route and continue using absolute paths for the root routes.
Example:
<BrowserRouter>
<Routes>
<Route path="/" element={<App />} />
<Route path="/home" element={<Homepage />} />
</Routes>
</BowserRouter>
I found the issue
I had to
<Route path="" element={<App/>}>
<Route path="/" element={<Homepage />} />
Delete the Path / in App and only add Path / in Homepage.
It works now
Related
I'm using react-router#6 and createBrowseRouter. Navigating via links on page works well and the URL is updating, but when refreshing or trying to access the path directly, the user is sent to the index route.
My basic router structure looks like this:
Routes.js
const router = createBrowserRouter(
createRoutesFromElements(
<Route
path="/"
element={
<Root
...some props
/>
}
loader={some loader...}
action={some action...}
>
<Route index element={<Home />} exact />
<Route path="templates/:id">
<Route
index
element={<Document />}
errorElement={some error element...}
loader={some loader...}
action={some action...}
/>
<Route
path="edit"
element={
<EditDocument ...some props />
}
loader={some loader...}
action={some action...}
/>
</Route>
<Route path="settings" element={<Settings />} />
</Route>
)
)
So basically a root route with some nested routes. At the bottom of this component, I'm returning like this: return <RouterProvider router={router} />;
The Routes component in the Routes.js is rendered via an App.js, in which I'm loading some data and passing that data via props (to the Routes component). The App.js is rendered via index.js.
My feeling is that the general structure of my routes is incorrect, but I'm not sure. I believe I followed some official React Router v6 sample code.
I am having issues converting my code from meeting React-Router-Dom v5 requirements to V6 requirements. For some reason my webpage contents are not loading in the browser. Any help please? Ive tried doing the research and implementing different solutions but I havnt been able to fix the issue.
Here is my App.js
https://i.stack.imgur.com/USV67.png
Here is my index.js
https://i.stack.imgur.com/KG96P.png
Move TopBar out of the Routes component and move the Single component onto the route's element prop. The only valid children of the Routes component are the React.Fragment and Route components, and the only valid children of the Route component are other Route components.
Example:
function App() {
const user = false;
return (
<>
<TopBar />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/register" element={<Register />} />
<Route path="/login" element={<Login />} />
<Route path="/write" element={<Write />} />
<Route path="/settings" element={<Settings />} />
<Route path="/post/:postId" element={<Single />} />
</Routes>
</>
);
}
This is my router structure:
<Router>
<main className="py-3">
<Switch>
<Container>
<Route exact path="/admin" component={AdminScreen}></Route>
<Route path="/:campaignId" component={CampaignScreen}></Route>
<Route path="/" component={HomeScreen} exact></Route>
</Container>
</Switch>
</main>
</Router>
For "some" reason, when I go to /admin i also get the CampaignScreen rendered.
I added the <Switch> as you can see, but it does not seem to help.
Where lies the problem?
Since admin can theoretically also be a campaignId react router thinks it matches both routes, and you have the <Container> element directly inside the Switch it still renders both, the solution is to have your routes directly in the Switch
I am building a React app that has a static marketing site and a dynamic app. I am using a combination of React Router and hooks to separate the two and ensure proper routing throughout.
To begin with, I want users who are logged in to be taken directly to the app when they hit the root ("/") and to the static/marketing site when not logged in. The main marketing site home page has a nav bar that allows users to access other routes such as "/about", whereas the app has a separate nav bar for app navigation.
The problem is, while the authentication based routing for the root route seems to be working, and I can navigate to other routes specified in my top-level file, the routes that are included within my static/marketing site are not accessible.
Top-level/index.js
const routing = (
<Provider store={store}>
<Router>
<NavWrapper />
{/* <Switch> */}
<Route exact path="/" component={AuthWrapper} />
<Route path="/signup" component={SignUp} />
<Route path="/login" component={Login} />
{/* </Switch> */}
</Router>
</Provider>
)
ReactDOM.render(routing, document.getElementById('root'));
AuthWrapper.js (here useAuth() is a React hook that evaluates global Redux isAuthenticated state)
const AuthWrapper = (props) => {
return useAuth() ? <App /> : <Website />
}
export default AuthWrapper;
website/index.js
export const Website = () => {
return (
<>
{/* <SiteNav /> */}
<Switch>
<Route exact path="/" component={LandingPage} />
<Route path="/about" component={AboutPage} />
<Route path="/how-it-works" component={HowItWorksPage} />
<Route path="/plans" component={PlansPage} />
<Route path="/press" component={PressPage} />
<Route path="/faq" component={FAQPage} />
<Route path="/legal" component={LegalPage} />
<Route path="/for-dieticians" component={DietitiansPage} />
<Route path="/for-trainers" component={PTsPage} />
</Switch>
</>
)
};
In my app, when I enter localhost:3000/ (unauthenticated) I am correctly taken to my home/landing page. However, if I try to use the navigation (or type in any subroutes) to access "/about" for example, I get a blank screen (other than the nav bar). In the React dev tools, the component isn't even rendering.
I think this is the issue:
<Route exact path="/" component={AuthWrapper} />
You want Authwrapper to be shown for about as well, right? But the above only matches "/" exactly.
You should enable the switch statement, but move the AuthWrapper Route to the bottom and then let it have this path: "/:rest*" (maybe "/*" works too, haven't used react-router in a while).
That way, it will use the Route if the first 2 don't match.
I'm new to react and learning how to react-router to achieve routing. As a part of my sample app I was trying to put an authenticator on every path that's a part of the site. I'm following this example: https://github.com/reactjs/react-router/blob/master/examples/auth-flow/app.js
And here is my sample code:
render(
<Router history={browserHistory}>
<Route path="/" component={App} onEnter={requireAuth}>
<IndexRoute component={Home}/>
<Route path="login" component={Login}/>
<Route path="logout" component={Logout}/>
<Route path="about" component={About}/>
<Route path="inbox" component={Inbox}/>
</Route>
</Router>,
document.getElementById("app"));
And here is what requireAuth does:
function requireAuth(nextState, replace) {
if(!auth.isUserLoggedIn()) {
replace({
path: "/login",
state: {nextPathname: nextState.location.pathname}
});
}
}
The difference between what I'm doing and what the example does is that the example puts the auth functionality only on one route (dashboard), where as I want to put it on every route. But the example stops working and starts throwing error
Maximum call stack size exceeded
and I think rightly so because /login is a subroute of / and because requireAuth is redirecting to the sub route, it just try to authenticate again and keeps trying for ever. I'm probably missing a simple fix here to get this to work, but am not able to figure what is the best way to do it.
What can I do to enable authentication at every level of the site?
Answer of #DemoUser is almost correct and #KumarM how you can login if you need to be authenticated to see login page ? here is what you can do
render(
<Router history={browserHistory}>
<Route path="/" component={App}>
<Route path="login" component={Login}/>
<Route path="logout" component={Logout}/>
<Route path="/dashboard" onEnter={requireAuth} >
<IndexRoute component={Home}/>
<Route path="about" component={About}/>
<Route path="inbox" component={Inbox} />
</Route>
</Route>
</Router>,
document.getElementById("app"));
whats happening here ?
login and logout page need not to be authenticated
all child components of Dashboard will automatically be authenticated
I think you must've figured it out by now but I stumbled across this today, so I thought of sharing this:
If you are adamant on securing every resource of your application, I'd suggest thinking twice. What #abhirathore2006 said is: users of your application shouldn't be authenticated to access the login component. Should they?
You are correct in assuming that the 'Maximum call stack size increased' is because of infinite redirects happening and you can try to avoid it by doing a null check or something.
The point is, you'd just need to place the onEnter hook on the /logout, /inbox & /about components and leave the /login as is. Otherwise you could try wrapping these components in a HOC or use the newer react-router4 approach to get what you need.
Hope this helps!
Cheers!
You could change your route so that, the pages that do not require login, can be rendered without need of authentication, as:
render(
<Router history={browserHistory}>
<Route path="/" component={App}>
<IndexRoute component={Home}/>
<Route path="login" component={Login}/>
<Route path="logout" component={Logout}/>
<Route path="about" component={About}/>
<Route path="inbox" component={Inbox} onEnter={requireAuth}/>
</Route>
</Router>,
document.getElementById("app"));
If user is already loggedin requireAuth does not do anything, and your Inbox component is rendered.