From 6b7307355758a49ef8909160200ae9f70f827a2d Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Tue, 27 Dec 2016 08:41:23 -0800 Subject: [PATCH] Include owner in invalid element type invariant (#8637) --- scripts/fiber/tests-failing.txt | 6 ------ scripts/fiber/tests-passing.txt | 2 ++ .../shared/fiber/ReactDebugCurrentFiber.js | 21 ++++++++++++++++--- src/renderers/shared/fiber/ReactFiber.js | 9 +++++++- .../ReactIncrementalErrorHandling-test.js | 4 ++-- 5 files changed, 30 insertions(+), 12 deletions(-) diff --git a/scripts/fiber/tests-failing.txt b/scripts/fiber/tests-failing.txt index 63224fd19b21..ebf46e20be28 100644 --- a/scripts/fiber/tests-failing.txt +++ b/scripts/fiber/tests-failing.txt @@ -9,9 +9,6 @@ src/addons/__tests__/ReactFragment-test.js src/isomorphic/classic/__tests__/ReactContextValidator-test.js * should pass previous context to lifecycles -src/isomorphic/classic/element/__tests__/ReactElementValidator-test.js -* includes the owner name when passing null, undefined, boolean, or number - src/renderers/dom/__tests__/ReactDOMProduction-test.js * should throw with an error code in production @@ -63,9 +60,6 @@ src/renderers/shared/hooks/__tests__/ReactComponentTreeHook-test.js src/renderers/shared/hooks/__tests__/ReactHostOperationHistoryHook-test.js * gets recorded during an update -src/renderers/shared/shared/__tests__/ReactComponent-test.js -* includes owner name in the error about badly-typed elements - src/renderers/shared/shared/__tests__/ReactComponentLifeCycle-test.js * should carry through each of the phases of setup diff --git a/scripts/fiber/tests-passing.txt b/scripts/fiber/tests-passing.txt index 32be44b93826..cb3f467467f8 100644 --- a/scripts/fiber/tests-passing.txt +++ b/scripts/fiber/tests-passing.txt @@ -287,6 +287,7 @@ src/isomorphic/classic/element/__tests__/ReactElementValidator-test.js * does not warn when the array contains a non-element * should give context for PropType errors in nested components. * gives a helpful error when passing invalid types +* includes the owner name when passing null, undefined, boolean, or number * should check default prop values * should not check the default for explicit null * should check declared prop types @@ -1334,6 +1335,7 @@ src/renderers/shared/shared/__tests__/ReactComponent-test.js * should call refs at the correct time * fires the callback after a component is rendered * throws usefully when rendering badly-typed elements +* includes owner name in the error about badly-typed elements src/renderers/shared/shared/__tests__/ReactComponentLifeCycle-test.js * should not reuse an instance when it has been unmounted diff --git a/src/renderers/shared/fiber/ReactDebugCurrentFiber.js b/src/renderers/shared/fiber/ReactDebugCurrentFiber.js index 6b25a05ce032..881795cd1db7 100644 --- a/src/renderers/shared/fiber/ReactDebugCurrentFiber.js +++ b/src/renderers/shared/fiber/ReactDebugCurrentFiber.js @@ -15,6 +15,12 @@ import type { Fiber } from 'ReactFiber'; if (__DEV__) { + var { + IndeterminateComponent, + FunctionalComponent, + ClassComponent, + HostComponent, + } = require('ReactTypeOfWork'); var getComponentName = require('getComponentName'); var { getStackAddendumByWorkInProgressFiber } = require('ReactComponentTreeHook'); } @@ -25,10 +31,19 @@ function getCurrentFiberOwnerName() : string | null { if (fiber == null) { return null; } - if (fiber._debugOwner == null) { - return null; + switch (fiber.tag) { + case IndeterminateComponent: + case FunctionalComponent: + case ClassComponent: + return getComponentName(fiber); + case HostComponent: + if (fiber._debugOwner != null) { + return getComponentName(fiber._debugOwner); + } + return null; + default: + return null; } - return getComponentName(fiber._debugOwner); } return null; } diff --git a/src/renderers/shared/fiber/ReactFiber.js b/src/renderers/shared/fiber/ReactFiber.js index 26c8efa50700..ea0b88bb60e0 100644 --- a/src/renderers/shared/fiber/ReactFiber.js +++ b/src/renderers/shared/fiber/ReactFiber.js @@ -49,6 +49,10 @@ var { var invariant = require('invariant'); +if (__DEV__) { + var { getCurrentFiberOwnerName } = require('ReactDebugCurrentFiber'); +} + // A Fiber is work on a Component that needs to be done or was done. There can // be more than one per component. export type Fiber = { @@ -359,8 +363,11 @@ function createFiberFromElementType(type : mixed, key : null | string) : Fiber { ' You likely forgot to export your component from the file ' + 'it\'s defined in.'; } + const ownerName = getCurrentFiberOwnerName(); + if (ownerName) { + info += ' Check the render method of `' + ownerName + '`.'; + } } - // TODO: Stack also includes owner name in the message. invariant( false, 'Element type is invalid: expected a string (for built-in components) ' + diff --git a/src/renderers/shared/fiber/__tests__/ReactIncrementalErrorHandling-test.js b/src/renderers/shared/fiber/__tests__/ReactIncrementalErrorHandling-test.js index 84528ab2f2e5..c22d644fddd7 100644 --- a/src/renderers/shared/fiber/__tests__/ReactIncrementalErrorHandling-test.js +++ b/src/renderers/shared/fiber/__tests__/ReactIncrementalErrorHandling-test.js @@ -754,7 +754,7 @@ describe('ReactIncrementalErrorHandling', () => { 'Element type is invalid: expected a string (for built-in components) or ' + 'a class/function (for composite components) but got: undefined. ' + 'You likely forgot to export your component from the file it\'s ' + - 'defined in.' + 'defined in. Check the render method of `BrokenRender`.' )]); expect(console.error.calls.count()).toBe(1); }); @@ -798,7 +798,7 @@ describe('ReactIncrementalErrorHandling', () => { 'Element type is invalid: expected a string (for built-in components) or ' + 'a class/function (for composite components) but got: undefined. ' + 'You likely forgot to export your component from the file it\'s ' + - 'defined in.' + 'defined in. Check the render method of `BrokenRender`.' )]); expect(console.error.calls.count()).toBe(1); });