Skip to content

Unnecessary re-rendering under bailed-out components when a legacy context provider and a deep child are updated in the same batch #11508

@iamdustan

Description

@iamdustan

This issue is going to start off mostly theoretical as I’m still working to make a minimal repro case.

We have a scenario where one component is having shouldComponentUpdate() return false to bail out, but a child component is still having its render method called.

Avoiding many details this is roughly what we have:

import React, { Component } from 'react';

class A extends Component {
  shouldComponentUpdate(nextProps) {
    const result = Boolean(nextProps.item);
    console.log('A#shouldComponentUpdate?', result);
    return result;
  }

  render() {
    console.log('A#render', this.props.item);
    return <B item={this.props.item} />;
  }
}

class B extends Component {
  state = { seconds: 0 };
  componentDidMount() {
    this._interval = setInterval(
      () => this.setState({ seconds: this.state.seconds + 1 }),
      1000
    );
  }

  componentWillUnMount() {
    clearInterval(this._interval);
  }

  render() {
    console.log('B#render', this.props.item);
    return (
      <div>
        <strong>{this.props.item.name}</strong>
        <span>{this.state.seconds} seconds</span>
      </div>
    );
  }
}

export default A;

While this case does work as expected it seems to be in the direction of the
errors we’re seeing.

There is something taking place in our render cycle where B is being rendered
without reusing the item prop from the previous reconcile.

My first question is are there any theories on why this may be happening that I
can explore? We are using context as the parent of A and asB and these
are reading from a flux-thing (I think a fork of the original OSS Flux), they
they these are both passing all props through and not having any naming
collisions. I’m fairly certain we are not performing any mutations on our end.

(If I do manage to pull off a repro case I will immediately post it here with
utter joy in my heart)

cc @acdlite @gaearon (this is the issue I was asking about in Messenger recently)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions