Reputation: 2359
I'm trying to create an app with Reactjs + Redux + React router but I'm having some problems that I don't understand what it's causing it. Most probably I'm not fully understand how it works.
When I update the store of Redux all the components get re rendered instead of the ones where the state it's used. That means that my api calls for example are running twice when I simple show a flash message. EG:
render() {
const user = this.props.user;
if( ! user || ! user.token ) {
return (<Redirect
to={{
pathname: "/login",
state: {from: this.props.location}
}}
/>)
}
return (
<div className="app">
<Header {...this.props} />
<FlashMessage message={this.props.flash.message} type={this.props.flash.msg_type} {...this.props}/>
<div className="app-body">
<Sidebar {...this.props}/>
<main className="main">
<Breadcrumb />
<Container fluid>
<Switch>
<Route path="/settings/permissions/add" name="Add Permission"
component={() => <AddPermissionView {...this.props}/>}/>
<Route path="/settings/permissions/" name="Permissions"
component={() => <ListPermissions {...this.props}/>}/>
<Route path="/dashboard" name="Dashboard"
component={() => <Dashboard {...this.props}/>}/>
<Route path="/logout" name="Logout" component={() => <Redirect to="/login"/>}/>
<Redirect from="/" to="/dashboard"/>
</Switch>
</Container>
</main>
<Aside />
</div>
<Footer />
</div>
);
}
So for example if I update the store for flash message, the Flashmessage compoenent gets rendered as it should, but also the Dashboard,sidebar,Header, etc. I thought only the state that changed it's rendered again.
That means I need to use shouldComponentUpdate on every component I create to avoid that behaviour ?
Upvotes: 1
Views: 536
Reputation: 3411
Replace component props with the render prop in your routes.
<Route path="/settings/permissions/add" name="Add Permission" render={() => <AddPermissionView {...this.props}/>}/>
<Route path="/settings/permissions/" name="Permissions" render={() => <ListPermissions {...this.props}/>}/>
<Route path="/dashboard" name="Dashboard" render={() => <Dashboard {...this.props}/>}/>
<Route path="/logout" name="Logout" render={() => <Redirect to="/login"/>}/>
Upvotes: 1
Reputation: 10682
By default, updates to the Redux Store cause application-wide re-renders, regardless of where the update was applied in the Store. In case of small applications, this behavior is typically not noticeable. However, as an application (and its state tree) grows, its performance can be easily hampered by that blanket "re-render every component" strategy.
Fortunately, there are solutions to this problem. I use React Reselect, which helps create memoized selectors that help localize renders to components whose state was affected, leaving everything else unchanged:
https://github.com/reactjs/reselect
I'd suggest reading through the text on the page, perhaps twice, watching the video that's linked in the documentation, and actually doing an example project to understand how Redux works naturally, and how Reselect gets rid of unnecessary component re-renders via memoized selectors.
Upvotes: 0