diff --git a/packages/react-is/src/ReactIs.js b/packages/react-is/src/ReactIs.js index 085decb4a74f..98142d7e0177 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 1c47fd551bb5..ae2de7fe1cfe 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 e4e32bd00e35..6da646769862 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'; } }