diff --git a/packages/react-is/src/ReactIs.js b/packages/react-is/src/ReactIs.js
index 085decb4a74fe..98142d7e01775 100644
--- a/packages/react-is/src/ReactIs.js
+++ b/packages/react-is/src/ReactIs.js
@@ -48,14 +48,14 @@ export function typeOf(object: any) {
switch ($$typeofType) {
case REACT_CONTEXT_TYPE:
case REACT_FORWARD_REF_TYPE:
+ case REACT_LAZY_TYPE:
+ case REACT_MEMO_TYPE:
case REACT_PROVIDER_TYPE:
return $$typeofType;
default:
return $$typeof;
}
}
- case REACT_LAZY_TYPE:
- case REACT_MEMO_TYPE:
case REACT_PORTAL_TYPE:
return $$typeof;
}
diff --git a/packages/react-is/src/__tests__/ReactIs-test.js b/packages/react-is/src/__tests__/ReactIs-test.js
index 1c47fd551bb58..ae2de7fe1cfe5 100644
--- a/packages/react-is/src/__tests__/ReactIs-test.js
+++ b/packages/react-is/src/__tests__/ReactIs-test.js
@@ -71,6 +71,7 @@ describe('ReactIs', () => {
it('should identify context consumers', () => {
const Context = React.createContext(false);
+ expect(ReactIs.isValidElementType(Context.Consumer)).toBe(true);
expect(ReactIs.typeOf()).toBe(ReactIs.ContextConsumer);
expect(ReactIs.isContextConsumer()).toBe(true);
expect(ReactIs.isContextConsumer()).toBe(false);
@@ -79,6 +80,7 @@ describe('ReactIs', () => {
it('should identify context providers', () => {
const Context = React.createContext(false);
+ expect(ReactIs.isValidElementType(Context.Provider)).toBe(true);
expect(ReactIs.typeOf()).toBe(ReactIs.ContextProvider);
expect(ReactIs.isContextProvider()).toBe(true);
expect(ReactIs.isContextProvider()).toBe(false);
@@ -106,6 +108,7 @@ describe('ReactIs', () => {
it('should identify ref forwarding component', () => {
const RefForwardingComponent = React.forwardRef((props, ref) => null);
+ expect(ReactIs.isValidElementType(RefForwardingComponent)).toBe(true);
expect(ReactIs.typeOf()).toBe(ReactIs.ForwardRef);
expect(ReactIs.isForwardRef()).toBe(true);
expect(ReactIs.isForwardRef({type: ReactIs.StrictMode})).toBe(false);
@@ -113,6 +116,7 @@ describe('ReactIs', () => {
});
it('should identify fragments', () => {
+ expect(ReactIs.isValidElementType(React.Fragment)).toBe(true);
expect(ReactIs.typeOf()).toBe(ReactIs.Fragment);
expect(ReactIs.isFragment()).toBe(true);
expect(ReactIs.isFragment({type: ReactIs.Fragment})).toBe(false);
@@ -124,6 +128,7 @@ describe('ReactIs', () => {
it('should identify portals', () => {
const div = document.createElement('div');
const portal = ReactDOM.createPortal(
, div);
+ expect(ReactIs.isValidElementType(portal)).toBe(false);
expect(ReactIs.typeOf(portal)).toBe(ReactIs.Portal);
expect(ReactIs.isPortal(portal)).toBe(true);
expect(ReactIs.isPortal(div)).toBe(false);
@@ -131,21 +136,24 @@ describe('ReactIs', () => {
it('should identify memo', () => {
const Component = () => React.createElement('div');
- const memoized = React.memo(Component);
- expect(ReactIs.typeOf(memoized)).toBe(ReactIs.Memo);
- expect(ReactIs.isMemo(memoized)).toBe(true);
- expect(ReactIs.isMemo(Component)).toBe(false);
+ const Memoized = React.memo(Component);
+ expect(ReactIs.isValidElementType(Memoized)).toBe(true);
+ expect(ReactIs.typeOf()).toBe(ReactIs.Memo);
+ expect(ReactIs.isMemo()).toBe(true);
+ expect(ReactIs.isMemo()).toBe(false);
});
it('should identify lazy', () => {
const Component = () => React.createElement('div');
- const lazyComponent = React.lazy(() => Component);
- expect(ReactIs.typeOf(lazyComponent)).toBe(ReactIs.Lazy);
- expect(ReactIs.isLazy(lazyComponent)).toBe(true);
- expect(ReactIs.isLazy(Component)).toBe(false);
+ const LazyComponent = React.lazy(() => Component);
+ expect(ReactIs.isValidElementType(LazyComponent)).toBe(true);
+ expect(ReactIs.typeOf()).toBe(ReactIs.Lazy);
+ expect(ReactIs.isLazy()).toBe(true);
+ expect(ReactIs.isLazy()).toBe(false);
});
it('should identify strict mode', () => {
+ expect(ReactIs.isValidElementType(React.StrictMode)).toBe(true);
expect(ReactIs.typeOf()).toBe(ReactIs.StrictMode);
expect(ReactIs.isStrictMode()).toBe(true);
expect(ReactIs.isStrictMode({type: ReactIs.StrictMode})).toBe(false);
@@ -153,6 +161,7 @@ describe('ReactIs', () => {
});
it('should identify suspense', () => {
+ expect(ReactIs.isValidElementType(React.Suspense)).toBe(true);
expect(ReactIs.typeOf()).toBe(ReactIs.Suspense);
expect(ReactIs.isSuspense()).toBe(true);
expect(ReactIs.isSuspense({type: ReactIs.Suspense})).toBe(false);
@@ -161,6 +170,7 @@ describe('ReactIs', () => {
});
it('should identify profile root', () => {
+ expect(ReactIs.isValidElementType(React.Profiler)).toBe(true);
expect(
ReactIs.typeOf(),
).toBe(ReactIs.Profiler);
diff --git a/packages/react-test-renderer/src/ReactShallowRenderer.js b/packages/react-test-renderer/src/ReactShallowRenderer.js
index e4e32bd00e359..6da6467698624 100644
--- a/packages/react-test-renderer/src/ReactShallowRenderer.js
+++ b/packages/react-test-renderer/src/ReactShallowRenderer.js
@@ -542,7 +542,7 @@ class ReactShallowRenderer {
);
invariant(
isForwardRef(element) ||
- (typeof element.type === 'function' || isMemo(element.type)),
+ (typeof element.type === 'function' || isMemo(element)),
'ReactShallowRenderer render(): Shallow rendering works only with custom ' +
'components, but the provided element type was `%s`.',
Array.isArray(element.type)
@@ -559,7 +559,7 @@ class ReactShallowRenderer {
this._reset();
}
- const elementType = isMemo(element.type) ? element.type.type : element.type;
+ const elementType = isMemo(element) ? element.type.type : element.type;
const previousElement = this._element;
this._rendering = true;
@@ -567,7 +567,7 @@ class ReactShallowRenderer {
this._context = getMaskedContext(elementType.contextTypes, context);
// Inner memo component props aren't currently validated in createElement.
- if (isMemo(element.type) && elementType.propTypes) {
+ if (isMemo(element) && elementType.propTypes) {
currentlyValidatingElement = element;
checkPropTypes(
elementType.propTypes,
@@ -618,7 +618,7 @@ class ReactShallowRenderer {
this._mountClassComponent(elementType, element, this._context);
} else {
let shouldRender = true;
- if (isMemo(element.type) && previousElement !== null) {
+ if (isMemo(element) && previousElement !== null) {
// This is a Memo component that is being re-rendered.
const compare = element.type.compare || shallowEqual;
if (compare(previousElement.props, element.props)) {
@@ -807,7 +807,7 @@ function getDisplayName(element) {
} else if (typeof element.type === 'string') {
return element.type;
} else {
- const elementType = isMemo(element.type) ? element.type.type : element.type;
+ const elementType = isMemo(element) ? element.type.type : element.type;
return elementType.displayName || elementType.name || 'Unknown';
}
}