I'm fetching data from an API server to generate the NavBar Menu dynamically.
Problem is that the menu re-renders each time I navigate through the pages.
Can't figure out why it's happening. I tried different examples for react-router
v4 like using but the menu is always re-rendering.
What pattern do you use to prevent NavBar Menu from re-rendering when generating the Menu dynamically?
Here are the basic setup files:
Main.js file:
import React from 'react'
import { Route } from 'react-router-dom'
import Home2 from './Home'
import Head from './Head'
import Rules from './Rules'
const Main = () => (
<main>
<Route path='/' component={Head}/>
<Route exact path='/' component={Home}/>
<Route exact path='/rules' component={Rules}/>
</main>
)
export default Main
Head.js file:
import React, { Component } from 'react'
import Menu from 'semantic-ui-react'
class Head extends Component {
constructor(props) {
super(props);
}
getInitialData() {
//fetch data from server
}
componentWillMount() {
this.getInitialData();
}
render() {
return (
<header>
<nav>
<Menu>
{/* fetched data */}
</nav>
</header>
)
}
}
export default Head
Index.js file:
import React from 'react'
import { render } from 'react-dom'
import Main from './components/Main'
import { BrowserRouter } from 'react-router-dom'
render((
<BrowserRouter>
<Main />
</BrowserRouter>
), document.getElementById('root'));
Using React Router v3 this code works fine:
var Routes = (
<Router>
<Route path="/" component={Head}>
<IndexRoute component={Home} />
</Route>
</Router>
);
But in v4 I can't nest Routes.
But, is there an option to prevent re-rendering with functional components? The answer is yes! Use React. memo() to prevent re-rendering on React function components.
To restrict access to routes in React Router, we set the render prop to a function that renders the component we want according to the condition we're checking. import { Route, Redirect } from "react-router"; <Route exact path="/" render={() => (loggedIn ?
React Router overview add links for navigation. define the route of each page, meaning the URL path and the component that we want to load. define a router which will check if the requested URL is defined in the routes, and if it is, return the component.
Even though it is late, I thought I'd post the answer here for other people who might be struggling with this.
First of all, as per the answer by @JulesDupont, your <Head />
component should be outside of your routes.
const App = () => (
<>
<Head />
<Switch>
<Route exact path='/' component={Component 1}/>
// Add any other routes goes here
</Switch>
</>
)
export default App;
Additionally, the pattern that you are searching for is the use of the <Link>
tags from react-router-dom
. It would be great if you could post your Head component here. There is a strong chance that you are using <a href='/#'>
tags to redirect instead of <Link to='/#'>
tags inside of your <Menu />
.
<a>
tags would trigger an entire page reload, causing your <Head />
component to get re mounted each time you navigate to a new page, hence re-fetching all the data. However, the <Link>
tag does not not trigger full page reloads.
Example:
import { Link } from 'react-router-dom';
const Head = () => {
return (
<ul>
<Link to='/your-route'>Item 1 (fetches data)<Link>
<Link to='/your-other-route'>Item 2 (fetches data)</Link>
</ul>
)
}
export default Head;
This will ensure that your Head component does not re-render or re-fetches data when navigating to another route.
Because you're including the header as a route, it's re-rendering every time the route changes. Just pull the header out of the route and it will stay consistent while the route-based components change:
import React from 'react'
import { Route, Switch } from 'react-router-dom'
import Home2 from './Home'
import Head from './Head'
const Main = () => (
<main>
<Head />
<Switch>
<Route exact path='/' component={Home}/>
// Add any other routes you want here
</Switch>
</main>
)
export default Main;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With