Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React: Update Child Component Without Rerendering Parent

What follows is a simple example:

const { Component } = React
const { render } = ReactDOM

const Label = ({ text }) => (
  <p>{text}</p>
)

const Clock = ({ date }) => (
  <div>{date.toLocaleTimeString()}</div>
)

class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      date: new Date()
    }
  }
  
  componentDidMount() {
    this.interval = setInterval(
      () => this.setState({ date: new Date() }),
      1000
    )
  }
  
  componentWillUnmount() {
    clearInterval(this.interval)
  }
  
  updateTime() {
    
  }
  
  render() {
    return (
      <div>
        <Label text="The current time is:" />
        <Clock date={this.state.date} />
      </div>
    )
  }
  
}

render(<App />, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="app"></div>

this.setState({ date: new Date() }) is being called every second updating the Clock with the current time. To my knowledge, setState calls the render method on the App which causes the whole component to be rerendered including the Label.

Is there a way pass date to Clock (causing it to be rerendered) without rerendering the entirety of the App component? How big of a role does this play in regards to performance?

like image 566
Mateja Petrovic Avatar asked Aug 25 '18 14:08

Mateja Petrovic


People also ask

Does updating child component re-render parent?

No, it will not re-render. If you pass any props to the component from the parent component and you update that prop in children or that prop update in the parent component so both will re-render.

How do you stop child components from Rerendering in parent component renders?

If you don't want a component to re-render when its parent renders, wrap it with memo. After that, the component indeed will only re-render when its props change.

Does React always Rerender children?

Now, we know that React components re-render themselves and all their children when the state is updated. In this case, on every mouse move the state of MovingComponent is updated, its re-render is triggered, and as a result, ChildComponent will re-render as well.

How do you prevent components from Rerendering?

But, if we use the useMemo() Hook, we can avoid component re-rendering if the inputs are the same and save the result in the cache. Now, the computed result is stored in the cachedValue variable and useMemo() Hook will return it each time unless the inputs are changed.


1 Answers

When you want to update a child without updating the parent, the state must be in the child. You can pass the state getter / setter from the child to the parent to be able to read and update it:

function Child({onMount}) {
  const [value, setValue] = useState(0);

  useEffect(() => {
    onMount([value, setValue]);
  }, [onMount, value]);


  return (
    <div>
      {value}
    </div>    
  );
};


function Parent() {

  let value = null;
  let setValue = null;
  
  const onChildMount = (dataFromChild) => {
    value = dataFromChild[0];
    setValue = dataFromChild[1];
  };

  // Call setValue to update child without updating parent

  return (
    <div>
      <Child onMount={onChildMount}/>
    </div>    
  );
};

Since const [value, setValue] = useState(0); is in the Child, only the child component will re render when updating the value. Additionally, since the Parent receives value and setValue at onChildMount, the parent can use them to update the child without re rendering the parent.

like image 134
stbn Avatar answered Oct 03 '22 03:10

stbn