Right now it's only being applied to the default renderers, but there's a good chance that people don't implement them for custom renderers (the examples are a good example of omitting this) and it slows things down a lot. Instead, it might be nice to have them wrapped by default with a component with the proper shouldComponentUpdate, but then to allow for defining your own with a static property on the component like suppressShouldComponentUpdate or similar.
I currently do this with the following util.
pure.js
import React, { Component } from 'react';
import shallowEqual from 'fbjs/lib/shallowEqual';
/**
* Creates a pure component by wrapping the given Component so that the
* component only renders initially and when it receives new prop instances.
* A shallow equivalence on the wrapped component's props is done.
*/
function pure(WrappedComponent) {
class PureComponent extends Component {
shouldComponentUpdate(nextProps) {
return !shallowEqual(this.props, nextProps);
}
render() {
return <WrappedComponent {...this.props} />;
}
}
return PureComponent;
}
export default pure;
Then in my editor implementation:
const NODES = {
'block-quote': pure(props => <blockquote {...props.attributes}>{props.children}</blockquote>),
'bulleted-list': pure(props => <ul {...props.attributes}>{props.children}</ul>),
...
};
Note: you could expand the above to include a helpful displayName on the wrapped component. I do this with another set of helpers. It's useful for debugging in chrome.
@ctrlplusb no need for shallowEqual, slate is using Immutables.
A simple !== on immutable props would suffice
@arekkas yep, it is doing that. it's shallow comparing the props object which does a !== on each prop.
/**
* Performs equality by iterating through keys on an object and returning false
* when any key has values which are not strictly equal between the arguments.
* Returns true when the values of all keys are strictly equal.
*/
function shallowEqual(objA, objB) {
if (is(objA, objB)) {
return true;
}
if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
return false;
}
var keysA = Object.keys(objA);
var keysB = Object.keys(objB);
if (keysA.length !== keysB.length) {
return false;
}
// Test for A's keys different from B.
for (var i = 0; i < keysA.length; i++) {
if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
return false;
}
}
return true;
}
Ah right, thanks!
Done now by default for nodes!