Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Immutable.js with React Pure Components

I'm having some trouble using React PureComponents with Immutable.js. Consider the following demo:

https://codepen.io/SandoCalrissian/pen/QaEmeX

In it 2 components are rendered. The first (NoramlPure) is a normal PureComponent while the second (ImmutablePure) is a normal Component with a custom shouldComponentUpdate that checks props for an equals method. Both take a single Immutable Map as a prop which is re-formed on every render cycle. Both also print a message to the console every time they re-render.

I then trigger two render cycles.

I'm expecting both to only render once. However, the console shows the following:

rendering
    rendering normal pure component
    rendering immutable pure component
rendering
    rendering normal pure component

My custom component works as expected, but the built in PureComponent renders both times (despite getting the same data).

Seeing as React links to Immutable.js in the documentation for PureComponent (and since they're both made by Facebook) I'd sort of expect the two to work together naturally, but as far as I can tell PureComponents don't ever call any Immutable.js equality checkers.

Is there any way to make PureComponents work with Immutable.js objects? Or am I stuck using my PureImmutable component as a base-class across my entire project?

like image 378
Sandy Gifford Avatar asked Feb 01 '26 04:02

Sandy Gifford


1 Answers

Hi Sandy the problem is that in each render you are recreating the map prop and React.PureComponent is basically checking props.map === nextProps.map. They are different so it re-render.

Check this one:

class NormalPure extends React.PureComponent<any, any> {
  public render() {
    console.log("\trendering normal pure component");
    return <div />;
  }
}

class ImmutablePure extends React.Component<any, any> {
  public shouldComponentUpdate(nextProps) {
    return !Object.keys(this.props).every((key) => {
      const val = this.props[key];
      const nextVal = nextProps[key];

      if (typeof val.equals === "function")  {
        return val.equals(nextVal);
      } else {
        return val === nextVal;
      }
    });
  }

  public render() {
    console.log("\trendering immutable pure component");
    return <div />;
  }
}

const wrapper = document.getElementById("wrapper");

const obj = {
  "a": 1,
  "b": 2,
  "c": 3,
};

const immutableMap = Immutable.fromJS(obj);

function render() {
  console.log("rendering");

  ReactDOM.render(
    <div>
      <NormalPure map={immutableMap} />
      <ImmutablePure map={Immutable.fromJS(obj)} />
    </div>,
    wrapper
  );
}

render();
render();

Is there any way to make PureComponents work with Immutable.js objects? No. PureComponent use a strict equality comparison (===). It dosen't know about Immutablejs

Or am I stuck using my PureImmutable component as a base-class across my entire project? Yes, if you want to check Immutablejs objects with the equals method.

like image 171
Johnny Zabala Avatar answered Feb 02 '26 16:02

Johnny Zabala



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!