How to use {Switch, Route} in hierarchical components in React? - javascript

I have routes in App.js mainly Logout, Signin and Home.
Inside App.js :
return(
<>
<Switch>
<Route exact path='/' component={Home} />
<Route exact path='/signin' component={Signin} />
<Route exact path='/logout' component={Logout} />
</Switch>
</>)
Also, I want Routes inside Home.js :
return(
<>
<Navbar/>
<Switch>
<Route exact path='/'>
<LandingPage />
</Route>
<Route exact path='/settings'>
<Settings username={username} />
</Route>
</Switch>
</>
)
The LandingPage component is default for Home page, and Navbar is common in both LandingPage and Settings.
LandingPage component is showing perfectly but when I click "settings" button from Navbar, the Settings component is not showing. Other Routes are working fine.
Inside Navbar I used NavLink:
<NavLink className="nav-link" to="/">
HOME
</NavLink>
<NavLink className="nav-link" to="/settings">
SETTINGS
</NavLink>
Why the Settings Component is not showing ???

<Route exact path='/' component={Home} />
Because of the exact flag, anything that isn't precisely "/" will not match this. So when the url becomes "/settings", you stop rendering your Home component, which in turn means there's nothing trying to render a route at "/settings"
The likely fix is to remove the exact, and also rearrange your components so this case comes after the sign in/sign out cases:
<Switch>
<Route exact path='/signin' component={Signin} />
<Route exact path='/logout' component={Logout} />
<Route path='/' component={Home} />
</Switch>

Related

Layout is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>. How should I overcome this error?

<Routes>
<Route exact path='/'>
<Layout>
<Home></Home>
</Layout>
</Route>
</Routes>
Layout consists of header and footer, I want to wrap my home inside Layout.
React 18.1.0
react-router-dom 6.0.2
Other Route components are the only valid children of a Route component. This is the use case of building nested routes. For routed content/components, these must use the element prop.
Render the Layout component as the element of the Route component.
Example:
<Routes>
<Route
path='/'
element={(
<Layout>
<Home />
</Layout>
)}
/>
</Routes>
It also common to have layout components render an Outlet for nested routes.
Example:
const Layout = () => (
<>
<Header />
<Outlet />
<Footer />
</>
);
...
<Routes>
<Route element={<Layout />}>
<Route path='/' element={<Home />} />
</Route>
</Routes>
You could just extract the <Home/> component from there and provide the layout as a prop to the Route like this
<Route component={Layout} />
And provide your home component inside the Layout component it self

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 not rendering components at route

My root component is shown below:
ReactDOM.render(
<Provider store={store}>
<Router>
<Menu />
<Switch>
<Route path='/'>
<Home />
</Route>
<Route path='/about'>
<About />
</Route>
</Switch>
</Router>
</Provider>,
document.getElementById('root')
)
and then my Menu component is shown below:
function Menu() {
return (
<ul className='menu'>
<li className='menu-item'>
<Link to='/'>Home</Link>
</li>
<li className='menu-item'>
<Link to='/about'>About</Link>
</li>
</ul>
)
}
export default withRouter(Menu)
The problem is that when I click the relevant link, my About component does not render but the url shows up in the url bar. I am not sure what's wrong and I have gone through all of the questions related to this topic and none of their suggestions have helped me. I am using redux but I do not think that is what is causing the problem. Please help!
As mentioned, the exact prop should be added to the route that renders the Home component:
<Router>
...
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
...
</Router>
The reason for that is to restrict rendering of the Home component to an exact match of "/". Without the exact prop, the Home component will also be rendered for other partially matched routes (ie "/about", which would be considered a partial match).
Some other suggestions; you might consider assigning the component rendered for a route via the component prop on the Route component by doing this:
<Route exact path="/" component={Home} />
Additionally, you can avoid wrapping the Menu component with the withRouter.
For a working example, see this link - hope these pointers help! :)
add exactto your rout, like this
<Route exact path='/'>
<Home />
</Route>
<Route exact path='/about'>
<About />
</Route>
Use the Router logic like this.
<Provider store={store}>
<Router>
<Menu />
<Switch>
<Route path='/' exact component = {Home}/>
<Route path='/about' exact component = {About}/>
</Switch>
</Router>
</Provider>,

React + TypeScript with router deployement issue on Github Pages

Local runs fine, but when run on "npm run deploy" the website returns 404.
I have a React + TypeScript app which utilises react-router-dom BrowserRouter to navigate between pages.
I am ware of the issue on github pages with react-router, therefore I have tried adding basename={process.env.PUBLIC_URL}, changing it to a HashRouter, and many many more possibilities.
I've been on this issue for 7 hours straight... and there seems to be no resources on this particular problem for Typescript.
Could someone please help me!
index.tsx
ReactDOM.render(
<AppRouter />,
document.getElementById('root') as HTMLElement
);
Router.tsx
export const AppRouter: React.StatelessComponent<{}> = () => {
return (
<BrowserRouter basename={process.env.PUBLIC_URL}>
<div>
<NavBar />
<Switch>
<Route exact={true} path='/' component={App} />
<Route exact={true} path='/' component={Notes} />
<Route exact={true} path='/About' component={About} />
</Switch>
</div>
</BrowserRouter>
);
Also tried Router.tsx
export const AppRouter: React.StatelessComponent<{}> = () => {
return (
<HashRouter>
<div>
<NavBar />
<Switch>
<Route exact={true} path='/' component={App} />
<Route exact={true} path='/' component={Notes} />
<Route exact={true} path='/About' component={About} />
</Switch>
</div>
</HashRouter>
);
NavBar.tsx
export const NavBar: React.StatelessComponent<{}> = () => {
return (
<div id='nav-bar'>
<AppBar position='static' color='default'>
<Toolbar>
<span id='navbar-title'>
<Typography variant='title' color='default'>
Keep
</Typography>
</span>
<Link to="/">
<Button size="large" color="primary" variant="text">Notes</Button>
</Link>
<Link to="/About">
<Button size="large" color="primary" variant="text">About</Button>
</Link>
</Toolbar>
</AppBar>
</div>
)
Thank you for reading.
EDIT below is the exact error response from web console at 404 error. Something about favicon, could that be an issue? The location is completely wrong
json469.github.io/:1 Refused to load the image 'https://json469.github.io/favicon.ico' because it violates the following Content Security Policy directive: "img-src data:".
I've also tried debugging by printing out the process.env.PUBLIC_URL, however it returned an empty string...
EDIT2 below is the change made to Router.tsx that fixed the issue.
<HashRouter>
<div>
<NavBar />
<main>
<Switch>
<Route exact={true} path='/' component={App} />
<Route exact={true} path='/' component={Notes} />
<Route exact={true} path='/About' component={About} />
</Switch>
</main>
</div>
</HashRouter>
This is unlikely to be due to TypeScript - or even React Router. If you receive a 404, that is because your server has to redirect the user to your React app if they visit a route that the server does not know, and your app can then pretend to do actual routing.
However, it appears that GitHub Pages does not support this. Thus, you cannot do "proper" URLs like username.github.io/page/some-route. A workaround is to use the Hash Router, as you mentioned, but that means that URLs will look like username.github.io/page#/some-route.
Thus, your issue is probably that you're trying the former route, rather than the latter. So to solve it, you can either try that kind of route, or move to a different host.

React Route Component handle all "/" routes EXCEPT for "/login"

Dashboard component renders too, while I am entering /login. I need to omit Dashboard component while in Login.
Exact attribute does not fit because Dashboard has nested paths like /dashboard/users, /dashboard/settings
<BrowserRouter>
<Route path='/'>
<div>
<Route path='/login' component={Login} exact />
<Route path='/' component={Dashboard} />
</div>
</Route>
</BrowserRouter>
You could use Switch to render the first matching Route
<BrowserRouter>
<Route path='/'>
<div>
<Switch>
<Route path='/login' component={Login} exact />
<Route path='/' component={Dashboard} />
</Switch>
</div>
</Route>
</BrowserRouter>

Categories

Resources