Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React: Parent component re-renders all children, even those that haven't changed on state change

Tags:

reactjs

redux

I haven't been able to find a clear answer to this, hope this isn't repetitive.

I am using React + Redux for a simple chat app. The app is comprised of an InputBar, MessageList, and Container component. The Container (as you might imagine) wraps the other two components and is connected to the store. The state of my messages, as well as current message (the message the user is currently typing) is held in the Redux store. Simplified structure:

class ContainerComponent extends Component {   ...   render() {     return (       <div id="message-container">         <MessageList            messages={this.props.messages}         />         <InputBar            currentMessage={this.props.currentMessage}           updateMessage={this.props.updateMessage}           onSubmit={this.props.addMessage}         />       </div>     );   } } 

The issue I'm having occurs when updating the current message. Updating the current message triggers an action that updates the store, which updates the props passing through container and back to the InputBar component.

This works, however a side effect is that my MessageList component is getting re-rendered every time this happens. MessageList does not receive the current message and doesn't have any reason to update. This is a big issue because once the MessageList becomes big, the app becomes noticeably slower every time current message updates.

I've tried setting and updating the current message state directly within the InputBar component (so completely ignoring the Redux architecture) and that "fixes" the problem, however I would like to stick with Redux design pattern if possible.

My questions are:

  • If a parent component is updated, does React always update all the direct children within that component?

  • What is the right approach here?

like image 446
Nicholas Haley Avatar asked Nov 26 '16 15:11

Nicholas Haley


People also ask

Does React update all children components once the state of a parent has changed?

React schedules a render every time the state of a component changes.

Does child component Rerender if parent state changes?

State changes in Child component doesn't effect on the parent component, but when a state of parent component changes all the child components render.

Does React always re-render children?

Components always re-render There is a common misconception that a React component will not re-render unless one of its properties changes. This is not true: React does not care whether “props changed” - it will render child components unconditionally just because the parent rendered!

Does React re-render everything on state change?

React components automatically re-render whenever there is a change in their state or props. A simple update of the state, from anywhere in the code, causes all the User Interface (UI) elements to be re-rendered automatically.


1 Answers

If a parent component is updated, does React always update all the direct children within that component?

No. React will only re-render a component if shouldComponentUpdate() returns true. By default, that method always returns true to avoid any subtle bugs for newcomers (and as William B pointed out, the DOM won't actually update unless something changed, lowering the impact).

To prevent your sub-component from re-rendering unnecessarily, you need to implement the shouldComponentUpdate method in such a way that it only returns true when the data has actually changed. If this.props.messages is always the same array, it could be as simple as this:

shouldComponentUpdate(nextProps) {     return (this.props.messages !== nextProps.messages); } 

You may also want to do some sort of deep comparison or comparison of the message IDs or something, it depends on your requirements.

EDIT: After a few years many people are using functional components. If that's the case for you then you'll want to check out React.memo. By default functional components will re-render every time just like the default behavior of class components. To modify that behavior you can use React.memo() and optionally provide an areEqual() function.

like image 145
GJK Avatar answered Sep 29 '22 08:09

GJK