How to switch components using navigation in React? - javascript

I am developing a landing page using React. It should have the same navigation bar for all sections and change only its active state.
In App.js file I have used BrowserRouter that routes to Navigation component. My problem is that that Navigation does not work properly, it does not switch components, it switches only pathname. For example when I press Cabinet, it should switch from Home to Cabinet component. Should I use another router for Navigation or not? What would be the best solution for this?
I have tried to create NavRouter component, where I have placed routers for Navigation.
App.js file:
<BrowserRouter>
<Switch>
<Route path='/' exact component={ Navigation }></Route>
<Route path='/cabinet' component={ Navigation }></Route>
<Route path='/catalog' component={ Navigation }></Route>
<Route path='/company' component={ Navigation }></Route>
<Route path='/contacts' component={ Navigation }></Route>
</Switch>
</BrowserRouter>
Navigation file:
class Navigation extends Component {
render() {
const { classes, location: {pathname}, children } = this.props;
return (
<div>
<MuiThemeProvider theme={color}>
<Fragment>
<nav id="menu">
<ul className="navigation">
<li>
<MenuItem component={Link} to='/' selected={'/' === pathname} className="active menuItem" className={classes.menuItemColor}>
Главная
</MenuItem>
</li>
<li>
<MenuItem component={Link} to='/cabinet' selected={'/cabinet' === pathname} className="menuItem" className={classes.menuItemColor}>
Кабинет
</MenuItem>
</li>
<li>
<MenuItem component={Link} to='/catalog' selected={'/catalog' === pathname} className="menuItem" className={classes.menuItemColor}>
Каталог
</MenuItem>
</li>
<li>
<MenuItem component={Link} to='/company' selected={'/company' === pathname } className="menuItem" className="">
Компания
</MenuItem>
</li>
<li>
<MenuItem component={Link} to='/contacts' selected={'/contacts' === pathname} className="menuItem" className="">
Контакты
</MenuItem>
</li>
</ul>
</nav>
<main className={classes.content}>
{ children }
</main>
</Fragment>
</MuiThemeProvider>
</div>
);
}
}
NavRouter.js file:
<BrowserRouter>
<Navigation>
<Switch>
<Route path='/' exact component={ Navigation }></Route>
<Route path='/home' component={ Home }></Route>
</Switch>
</Navigation>
</BrowserRouter>

you can do the following:
create a file called Routes.js
in Routes.js:
export default () => (
<BrowserRouter>
<Switch>
<Route path='/' exact component={ Home }></Route>
<Route path='/cabinet' component={ Cabinet }></Route>
<Route path='/catalog' component={ Catalog }></Route>
<Route path='/company' component={ Company }></Route>
<Route path='/contacts' component={ Contacts }></Route>
</Switch>
</BrowserRouter>
)
in App.js
import Routes from './Routes';
import Navigation from './Navigation'
//inside render
<Navigation>
<Routes />
</Navigation>
Note: to get the current pathName, you have to use a state management solution like Redux.
Or: if you are not familiar with redux, for now instead of pathname in Navigation component you can use window.location.pathname

Here's the way to you need to do it. Separate the header navigation from the other components.
App.js
<Navigation/>
<BrowserRouter>
<Switch>
<Route path='/' exact component={ Home }></Route>
<Route path='/cabinet' component={ Cabinet }></Route>
<Route path='/catalog' component={ Catalog }></Route>
<Route path='/company' component={ Company }></Route>
<Route path='/contacts' component={ Contacts }></Route>
</Switch>
</BrowserRouter>

I have solved my problem by creating Root.js file, where I have placed my components
class Root extends Component {
render() {
return (
<div>
<MainNavigation />
<TopNav />
{this.props.children}
</div>
);
}
}
And in App.js file I have placed this:
<BrowserRouter>
<Root>
<Route path='/' exact component={ Home } />
<Route path='/cabinet' component={ Cabinet } />
<Route path='/catalog' component={ Catalog } />
<Route path='/company' component={ Company } />
<Route path='/contacts' component={ Contacts } />
</Root>
</BrowserRouter>

Related

react-router-dom v6 rendering new page over current page

the problem is the following. in the app.js is spelled out Routes and the home component. the home contains a navbar that navigates the site, only if you go to any page, it is drawn on top of the home. And if you switch to the home itself, it will be duplicated. Articles on the internet did not help, as did the addition of exact in route path.
function App() {
return (
<div className="messenger">
<Routes>
<Route path="/home/" element={<Home/>}/>
<Route path="/settings/" element={<Settings/>}/>
<Route path="/login/" element={<Login/>}/>
<Route path="/register/" element={<Register/>}/>
</Routes>
<Home/>
</div>
)
home
export default class Home extends Component {
render() {
return (
<div>
<NavBar/>
<ChatMenu/>
</div>
);
}
}
an example of how it is written in the navbar
export const NavBar = () => {
return (<div className="navbar-cm">
<div className="nav_element">
<Link to="/home">
<img src={homeIMG} className="nav_element"/>
</Link>
</div>
and a few more similar ones
</div>);
};
Issue
You are rendering the Home component again once outside the routes, this is why it's rendered with all routes including twice when on the "/home" path that renders Home.
function App() {
return (
<div className="messenger">
<Routes>
<Route path="/home/" element={<Home />} />
<Route path="/settings/" element={<Settings />} />
<Route path="/login/" element={<Login />} />
<Route path="/register/" element={<Register />} />
</Routes>
<Home /> // <-- always rendered below routed content
</div>
)
}
Solution
Remove the Home component that is out on its own outside the routes.
function App() {
return (
<div className="messenger">
<Routes>
<Route path="/home/" element={<Home />} /> // <-- now only Home component rendered
<Route path="/settings/" element={<Settings />} />
<Route path="/login/" element={<Login />} />
<Route path="/register/" element={<Register />} />
</Routes>
</div>
)
}
Remove <Home /> from the router:
function App() {
return (
<div className="messenger">
<Routes>
<Route path="/home/" element={<Home/>}/>
<Route path="/settings/" element={<Settings/>}/>
<Route path="/login/" element={<Login/>}/>
<Route path="/register/" element={<Register/>}/>
</Routes>
</div>
)

How can i render out the Nav component everywhere except the Login Page?

// MAIN FUNCTION { APP START }
const App = () => {
return (
<Router>
<Nav />
<Switch>
<Route to="/" exact component={Home} />
<Route to="/login" exact component={Login} />
</Switch>
</Router>
);
};
export default App;
I just want that the Nav component renders everywhere except the login page ??
You can put it inside a route component along with the Home.
<Router> <Switch>
<Route path="/" exact>
<Nav />
<Home />
</Route>
<Route to="/login" exact component={Login} />
</Switch> </Router>

why component in not loaded while using react router dom?

could you please tell me why component is not loaded when router changes
router file
export default function ForceLayoutRouter() {
return (
<Router>
<div>
<Switch>
<Route path="/calender" exact>
<ForceCalender />
</Route>
<Route path="/home" exact>
<Home />
</Route>
</Switch>
</div>
</Router>
);
}
link file
<Menu theme="dark" mode="inline" defaultSelectedKeys={["1"]}>
<Menu.Item key="1" icon={<UserOutlined />}>
<NavLink to={`/home`} exact>
Home ex
</NavLink>
</Menu.Item>
<Menu.Item key="2" icon={<CalendarOutlined />}>
<NavLink to={`/calender`}>Calender</NavLink>
</Menu.Item>
<Menu.Item key="3" icon={<LogoutOutlined />}>
Logout
</Menu.Item>
</Menu>
when I click home or calender link it change the router but component is not loaded.
here is my code
https://codesandbox.io/s/elated-black-3yozm?file=/src/components/layout.js:730-1230
You should wrap your app within a single Router. Try remove Router in your ForceLayoutRouter.
export default function ForceLayoutRouter() {
return (
<div>
<Switch>
<Route path="/calender" exact>
<ForceCalender />
</Route>
<Route path="/home" exact>
<Home />
</Route>
</Switch>
</div>
);
}
Here's the working codesandbox: https://codesandbox.io/s/crazy-grass-tnq63?file=/src/layout2.js

Meteor/React Router 4 - Homepage and connected user

Another post to ask you about a "situation" I am having, which is disappointing as my Router is creating too many refreshs and for the point is actually not to have to refresh part of the page by using React.
I would like the following :
When I go to './' and there is no user connected it shows a homepage (without header and footer)
When I go to './' and I am connected or any other link whether I am connected ot not it should show the relevant page with a Header and a Footer.
So the fact of being not connected does not show header/footer is only true for the './' address.
How I solved it and it is not satisfying because it seems my header is rerendering all the time I change pages even between two pages with Router....
I have a first Router, the AppRouter :
const AppRouter = () => (
<BrowserRouter>
<div className="content">
<Switch>
<Route path="/" component={Index} exact={true} />
<SubRouter />
</Switch>
</div>
</BrowserRouter>
);
export default AppRouter;
My index is like that :
export class Index extends React.Component {
render() {
if (this.props.user){
return (
<SubRouter />
)
} else {
return (
<Homepage />
)
}
}
}
So if no user the Homepage is showing if user it goes back to the SubRouter.
SubRouter is like that :
export class SubRouter extends React.Component {
(...)
render(){
return (
<div className="fullpage">
{this.state.inboxOpen ? <Inbox closeInbox={this.closeInbox} oneUserInboxId={this.state.oneUserInboxId} /> : undefined }
<Header openInbox={this.openInbox} closeInbox={this.closeInbox} />
<Switch>
<Route path="/" component={Dashboard} exact={true} />
<Route path="/admin" component={Admin} exact={true} />
<Route path="/account" component={Account} exact={true} />
<Route path="/settings" component={Settings} exact={true} />
<Route path="/faq" component={Faq} exact={true} />
<Route path="/cgv" component={Cgv} exact={true}/>
<Route path="/legal" component={Legal} exact={true}/>
<Route path="/login" component={Login} exact={true}/>
<Route path="/signup" component={Signup} exact={true}/>
<Route path="/notifications" render={() => (<Dashboard notifications={true} />)} exact={true} />
}} />
<Route path="/reset-password/:token" component={ResetPassword} />
<Route path="/forgot_password" component={ForgotPassword} exact={true} />
<Route path="/post/:postId" component={OnePost} />
<Route path="/*" component={NotFound} />
</Switch>
<Footer />
</div>
)
}
}
So this code is "working" but somehow we can see rerenders that should not happen, I am open to any idea to optimize this. Thanks in advance !
Problem was coming from here :
const AppRouter = () => (
<BrowserRouter>
<div className="content">
<Switch>
<Route path="/" component={Index} exact={true} />
<SubRouter />
</Switch>
</div>
</BrowserRouter>
);
export default AppRouter;
Should not have rerendered SubRouter here as it is already rendered in HomePage. Good code is :
const AppRouter = () => (
<BrowserRouter>
<div className="content">
<Switch>
<Route path="/" component={Index} exact={true} />
</Switch>
</div>
</BrowserRouter>
);
export default AppRouter;

React router error about redirecting to the current route. Unsure how to properly structure routes

I have a repo to reproduce this and see the error: https://github.com/rublev/parcel-static1/tree/master
The basic structure of my routes is as follows:
// app/app.js
const render = Component => {
ReactDOM.render(
<AppContainer>
<Provider store={ store }>
<ConnectedRouter history={ history }>
<Route component={ Component } />
</ConnectedRouter>
</Provider>
</AppContainer>,
document.getElementById('react-root')
)
}
// app/containers/App/index.js
<div className='app'>
<Switch location={ location }>
<Route exact path='/' render={() => (
loggedIn ? (
<Redirect to='/organizations' push />
) : (
<Redirect to='/onboarding' push />
)
)}/>
<Route path='/organizations' component={ Organizations } />
<Route path='/onboarding' component={ Onboarding } />
<Route path='/settings' component={ Settings } />
</Switch>
</div>
// app/flows/onboarding/Onboarding/index.js
<div>
<Route exact path={`${match.url}`} component={ Start }/>
<Route path={`${match.url}/signup`} component={ SignUp }/>
<Route path={`${match.url}/name`} component={ Name }/>
<Route path={`${match.url}/structure`} component={ Structure }/>
<Route path={`${match.url}/pricing`} component={ Pricing }/>
<Route path={`${match.url}/continue`} component={ Continue }/>
</div>
// app/flows/onboarding/Start/index.js
<div className='start'>
Start Page
</div>
I'm not sure where the error could be coming from or how to do this different.
I have three main routes:
/onboarding
/organizations
/settings
I'd like to redirect to either /onboarding or /settings depending on login state. Once at either of these main routes, there will be sub routes.
What is the proper way to set these routes up with a redirect without causing a redirect error?
error on launching localhost:8080/:
In your render function, change
<Route component={ Component } />
to
<Component />
Also, you shouldn't need to pass location as a prop into the Switch in App.

Categories