Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How will React 0.14's Stateless Components offer performance improvements without shouldComponentUpdate?

This question has been going round and round in my head since I read the release notes (and other related hype) around React 0.14 - I'm a big fan of React and I think that stateless components (https://facebook.github.io/react/blog/2015/09/10/react-v0.14-rc1.html#stateless-function-components) are an excellent idea, both for the ease of writing such components and for expressing in code the intention that these components should be "pure" in terms of rendering consistently for the same props data.

The question is: how will it be possible for React to optimise these stateless component functions without going whole-hog and assuming that props references are not only immutable in that they shouldn't be manipulated within the component, but also that they can never change outside of the component lifecycle? The reason that "regular" components (aka stateful components - in other words, the components that go through the whole lifecycle; componentWillMount, getInitialState, etc..) have an optional "shouldComponentUpdate" function is that React does not assume that all props and state references are completely immutable. After components have been rendered, certain properties of the props references may change and so the same "props" instance may have different contents later on. This is partially why there was a lot of excitement over the use of fully-immutable structures and why it was said that using Om with React could offer great performance gains; because the immutable structures used there guaranteed that any given instance of any object could never be mutated, so shouldComponentUpdate could perform really cheap reference equality checks on props and state (http://swannodette.github.io/2013/12/17/the-future-of-javascript-mvcs/).

I've been trying to find out more information about this but haven't got anywhere. I can't envisage what performance improvements could be made around stateless components without presuming that props data will consist of immutable types.. maybe some preliminary analysis of non-immutable props types to try to guess whether "props" and "nextProps" represent the same data?

I just wondered if anyone had any inside information or some otherwise enlightening insights onto this. If React did start demanding that props types be "fully immutable" (allow reference equality comparisons to confirm that data has not changed) then I think that would be a great step forward, but it could also be a big change.

like image 942
Dan Roberts Avatar asked Nov 14 '15 00:11

Dan Roberts


2 Answers

Since your component is just a pure function of its parameters, it would be straightforward to cache it. This is because of the well known property of pure functions, for same input they will always return same output. Since they only depend on their parameters alone, not some internal or external state. Unless you explicitly referred some external variables within that function that might be interpreted as a state change.

However, caching would not be possible if your function component reads some external variables to compose the return value, so that, those external variables might change over time, making cached value obsolete. This would be a violation of being a pure function anyways and they wont be pure anymore.

On React v0.14 Release Candidate page, Ben Alpert states:

This pattern is designed to encourage the creation of these simple components that should comprise large portions of your apps. In the future, we’ll also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations.

I am pretty sure that he meant cacheability of pure functional components.

Here is a very straight forward cache implementation for demonstration purposes:

let componentA = (props) => {
  return <p>{ props.text }</p>;
}

let cache = {};
let cachedA = (props) => {
  let key = JSON.stringify(props); // a fast hash function can be used as well
  if( key in cache ) {
    return cache[key];
  }else {
    cache[key] = componentA(props);
    return cache[key];
  }
}

And there are other good properties of pure functional components that I can think of at the moment:

  • unit test friendly
  • more lightweight than class based components
  • highly reusable since they are just functions
like image 80
Kemal Dağ Avatar answered Oct 02 '22 17:10

Kemal Dağ


Avoiding Unnecessary Allocations

If I understand correctly, stateless functional components are converted into regular components. From the source:

function StatelessComponent(Component) {
}
StatelessComponent.prototype.render = function() {
  var Component = ReactInstanceMap.get(this)._currentElement.type;
  return Component(this.props, this.context, this.updater);
};

When an instance of a stateless component is created, a new object is allocated. This new object has lifecycle methods such as componentWillMount and componentWillReceiveProps. I'm guessing that the plan is to not create these objects at all. Not creating the objects will avoid unnecessary allocations.

Avoiding Unnecessary Checks

Implementing the lifecycle methods requires a number of checks like this:

if (inst.componentWillUpdate) {
  inst.componentWillUpdate(nextProps, nextState, nextContext);
}

Stateless functional components can be assumed to not have these lifecycle methods. That could be what the docs are referring to, but I'm not sure.

EDIT

Removed stuff on memoization, which didn't answer the question or explain stuff well.

like image 24
Max Heiber Avatar answered Oct 02 '22 16:10

Max Heiber