chifliiiii
chifliiiii

Reputation: 2359

React component being re rendered

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

Answers (2)

Omar
Omar

Reputation: 3411

Render Prop and Component Prop inside of Route.

  • When you use component instead of render the router uses React.createElement to create a new React element from the given component.
  • if you provide an inline function to the component prop, you would create a new component every render.
  • This results in the existing component unmounting and the new component mounting instead of just updating the existing component.

Solution

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

Arash Motamedi
Arash Motamedi

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

Related Questions