Merge pull request #4859 from zpao/stateless-arrow-functions

Support native arrow functions as stateless components
This commit is contained in:
Paul O’Shannessy
2015-09-16 12:02:38 -07:00
2 changed files with 35 additions and 10 deletions
@@ -42,7 +42,7 @@ function StatelessComponent(Component) {
}
StatelessComponent.prototype.render = function() {
var Component = ReactInstanceMap.get(this)._currentElement.type;
return new Component(this.props, this.context, this.updater);
return Component(this.props, this.context, this.updater);
};
/**
@@ -136,18 +136,26 @@ var ReactCompositeComponentMixin = {
var inst;
var renderedElement;
if (__DEV__) {
ReactCurrentOwner.current = this;
try {
// This is a way to detect if Component is a stateless arrow function
// component, which is not newable. It might not be 100% reliable but is
// something we can do until we start detecting that Component extends
// React.Component. We already assume that typeof Component === 'function'.
var canInstantiate = 'prototype' in Component;
if (canInstantiate) {
if (__DEV__) {
ReactCurrentOwner.current = this;
try {
inst = new Component(publicProps, publicContext, ReactUpdateQueue);
} finally {
ReactCurrentOwner.current = null;
}
} else {
inst = new Component(publicProps, publicContext, ReactUpdateQueue);
} finally {
ReactCurrentOwner.current = null;
}
} else {
inst = new Component(publicProps, publicContext, ReactUpdateQueue);
}
if (inst === null || inst === false || ReactElement.isValidElement(inst)) {
if (!canInstantiate || inst === null || inst === false || ReactElement.isValidElement(inst)) {
renderedElement = inst;
inst = new StatelessComponent(Component);
}
@@ -168,7 +176,9 @@ var ReactCompositeComponentMixin = {
// We support ES6 inheriting from React.Component, the module pattern,
// and stateless components, but not ES6 classes that don't extend
warning(
Component.isReactClass || !(inst instanceof Component),
Component.isReactClass ||
!canInstantiate ||
!(inst instanceof Component),
'%s(...): React component classes must extend React.Component.',
Component.displayName || Component.name || 'Component'
);
@@ -183,4 +183,19 @@ describe('ReactStatelessComponent', function() {
ReactDOM.render(<Parent />, el);
expect(el.textContent).toBe('en');
});
it('should work with arrow functions', function() {
// TODO: actually use arrow functions, probably need node v4 and maybe
// a separate file that we blacklist from the arrow function transform.
// We can't actually test this without native arrow functions since the
// issues (non-newable) don't apply to any other functions.
var Child = function() {
return <div />;
};
// Will create a new bound function without a prototype, much like a native
// arrow function.
Child = Child.bind(this);
expect(() => ReactTestUtils.renderIntoDocument(<Child />)).not.toThrow();
});
});