I am quite new to React.js but I'm building a single page application using it. For routing I am using react-router.
The way I want to organize my page is as following: I want to have an static header and footer(loaded only ONCE), and then the content of the page that will change depending on the route. Nothing special here, this is basically my understanding of SPA.
This is the main.js that bootstraps my app with the routes:
const store = configureStore();
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<Route path="/" component={App}>
<IndexRoute component={Home}/>
<Route path="shop-filters-left-3cols" component={ShopFiltersLeft3Cols}/>
<Route path="about" component={About}/>
<Route path="login" component={Login}/>
</Route>
</Router>
</Provider>,
document.getElementById('main')
);
And this is the component App which is basically containing the structure of the single page:
export class App extends React.Component {
constructor(){
super();
this.render = this.render.bind(this);
}
render() {
console.log('Rendering App');
return (<div>
<LoginModal />
<Header/>
<div className="page-content">
{this.props.children}
</div>
<Footer/>
</div>);
}
}
So when I access the app, the component 'App' is loaded, and then the component 'Home' in injected into the main content as it is declared as IndexRoute.
Everything is fine until here, the problem is that every time I switch from a route to another, the component 'App' gets rendered( I know it because I see the 'Rendering App' log in the console). And this is what I don't understand, to my understanding, switching between routes shouldn't trigger a render of the 'App' component but only of the component that is being injected dynamically.
I don't want the header and footer to be rendered every time I switch a route, this is IMHO the benefit of having a single page application. Maybe I'm not understading well how react-router works, could someone please help me with that? Or if I'm doing something wrong please tell me what is the right way to achieve what I need.
If you need to see any other code don't hesitate to ask. Thank you
The App
component is re-rendered because you said it was the root of the view:
<Route path="/" component={App}>
This is not a problem. React is designed to re-render Components
, and you should write yours with that in mind.
Unlike most templating systems out there, what React calls rendering does not necessarily involve DOM changes. When React "re-renders" a Component
, it computes the minimum set of operations that will take the DOM from its current state to its desired state. This may be an empty set.
In other words, for your Components
that produce the same HTML, nothing will be actually done. Your header and footer probably fall into this category.
This makes it very fast. If performance is your concern, you can safely push it out of your mind for everything except the most demanding computational scenarios.
If you really want to, you can avoid the re-rendering of your Component
by implementing the shouldComponentUpdate()
method.
This is not encouraged: React is moving towards stateless, functional components, and you should try to use them whenever possible. Your job in this case is to guarantee that the same props
will render the same HTML. React's magical engine will do the rest.