Avoid React lifecycle overhead for wrapped functional components
Styles are used everywhere throughout a React render tree, which means that this HOC may be used on every component being rendered. This can potentially double the size of the React tree, so we want this HOC to be as fast as we can possibly make it. Unfortunately, we pay a small cost for every React component because React will run lifecycle events.
However, if we can determine that the WrappedComponent is a functional
component, we can call the function directly and avoid this overhead.
For this pass I decided to do this by checking for the existence of
render on the wrapped component's prototype, but there might be a
better way that I don't know about.
This type of optimization may end up being baked into React itself in the future, at which point we won't need to do this anymore. But in the meantime, let's make things a bit faster.
The biggest side-effect of this change is that we completely drop the
React component from the tree, which means that devtools and tests might
be a little less consistent (as you can see evidenced by no longer
needing to call dive() in our tests here for these wrapped functional
components). I think this is an acceptable tradeoff to make.
It also occurs to me that we can probably similarly decide to use either a class or a functional component to wrap the component, to match the type of component it is. This would end up breaking refs that already exist, but it would essentially make the wrapping component more transparent. But, I don't see any real benefits to that at this time, so I'll leave that breaking change for another time.
@airbnb/webinfra @lelandrichardson
Opening https://github.com/airbnb/react-with-styles/pull/70 to hopefully fix the build.
This seems like it should be a semver major change, no?
@lelandrichardson yeah, I was a little on the fence but I think you are right.