diff --git a/src/renderers/dom/fiber/wrappers/ReactDOMFiberInput.js b/src/renderers/dom/fiber/wrappers/ReactDOMFiberInput.js index 01ee87f95d..ebc9812077 100644 --- a/src/renderers/dom/fiber/wrappers/ReactDOMFiberInput.js +++ b/src/renderers/dom/fiber/wrappers/ReactDOMFiberInput.js @@ -94,7 +94,7 @@ var ReactDOMInput = { ReactControlledValuePropTypes.checkPropTypes( 'input', props, - getCurrentFiberOwnerName(), + getCurrentFiberStackAddendum, ); if ( diff --git a/src/renderers/dom/fiber/wrappers/ReactDOMFiberSelect.js b/src/renderers/dom/fiber/wrappers/ReactDOMFiberSelect.js index 2ceb3114b1..4659ec7f01 100644 --- a/src/renderers/dom/fiber/wrappers/ReactDOMFiberSelect.js +++ b/src/renderers/dom/fiber/wrappers/ReactDOMFiberSelect.js @@ -23,6 +23,10 @@ var ReactControlledValuePropTypes = require('ReactControlledValuePropTypes'); var {getCurrentFiberOwnerName} = require('ReactDebugCurrentFiber'); var warning = require('fbjs/lib/warning'); +if (__DEV__) { + var {getCurrentFiberStackAddendum} = require('ReactDebugCurrentFiber'); +} + var didWarnValueDefaultValue = false; function getDeclarationErrorAddendum() { @@ -42,7 +46,7 @@ function checkSelectPropTypes(props) { ReactControlledValuePropTypes.checkPropTypes( 'select', props, - getCurrentFiberOwnerName(), + getCurrentFiberStackAddendum, ); for (var i = 0; i < valuePropNames.length; i++) { diff --git a/src/renderers/dom/fiber/wrappers/ReactDOMFiberTextarea.js b/src/renderers/dom/fiber/wrappers/ReactDOMFiberTextarea.js index 43c91a3623..2f99352a0a 100644 --- a/src/renderers/dom/fiber/wrappers/ReactDOMFiberTextarea.js +++ b/src/renderers/dom/fiber/wrappers/ReactDOMFiberTextarea.js @@ -19,11 +19,14 @@ type TextAreaWithWrapperState = HTMLTextAreaElement & { }; var ReactControlledValuePropTypes = require('ReactControlledValuePropTypes'); -var {getCurrentFiberOwnerName} = require('ReactDebugCurrentFiber'); var invariant = require('fbjs/lib/invariant'); var warning = require('fbjs/lib/warning'); +if (__DEV__) { + var {getCurrentFiberStackAddendum} = require('ReactDebugCurrentFiber'); +} + var didWarnValDefaultVal = false; /** @@ -69,7 +72,7 @@ var ReactDOMTextarea = { ReactControlledValuePropTypes.checkPropTypes( 'textarea', props, - getCurrentFiberOwnerName(), + getCurrentFiberStackAddendum, ); if ( props.value !== undefined && diff --git a/src/renderers/dom/shared/utils/ReactControlledValuePropTypes.js b/src/renderers/dom/shared/utils/ReactControlledValuePropTypes.js index 0f8b44bc81..48c37b67a3 100644 --- a/src/renderers/dom/shared/utils/ReactControlledValuePropTypes.js +++ b/src/renderers/dom/shared/utils/ReactControlledValuePropTypes.js @@ -61,19 +61,13 @@ var propTypes = { }; var loggedTypeFailures = {}; -function getDeclarationErrorAddendum(ownerName) { - if (ownerName) { - return '\n\nCheck the render method of `' + ownerName + '`.'; - } - return ''; -} /** * Provide a linked `value` attribute for controlled forms. You should not use * this outside of the ReactDOM controlled form components. */ var ReactControlledValuePropTypes = { - checkPropTypes: function(tagName, props, ownerName) { + checkPropTypes: function(tagName, props, getStack) { for (var propName in propTypes) { if (propTypes.hasOwnProperty(propName)) { var error = propTypes[propName]( @@ -90,8 +84,7 @@ var ReactControlledValuePropTypes = { // same error. loggedTypeFailures[error.message] = true; - var addendum = getDeclarationErrorAddendum(ownerName); - warning(false, 'Failed form propType: %s%s', error.message, addendum); + warning(false, 'Failed form propType: %s%s', error.message, getStack()); } } }, diff --git a/src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js b/src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js index 08e53783f8..ac76902e0c 100644 --- a/src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js +++ b/src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js @@ -642,6 +642,13 @@ describe('ReactDOMInput', () => { , ); expectDev(console.error.calls.count()).toBe(1); + expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe( + 'Warning: Failed form propType: You provided a `value` prop to a form ' + + 'field without an `onChange` handler. This will render a read-only ' + + 'field. If the field should be mutable use `defaultValue`. ' + + 'Otherwise, set either `onChange` or `readOnly`.\n' + + ' in input (at **)', + ); }); it('should have a this value of undefined if bind is not used', () => { diff --git a/src/renderers/dom/stack/client/wrappers/ReactDOMInput.js b/src/renderers/dom/stack/client/wrappers/ReactDOMInput.js index 8e7f6de01a..cf0bb9cadc 100644 --- a/src/renderers/dom/stack/client/wrappers/ReactDOMInput.js +++ b/src/renderers/dom/stack/client/wrappers/ReactDOMInput.js @@ -83,11 +83,8 @@ var ReactDOMInput = { mountWrapper: function(inst, props) { if (__DEV__) { var owner = inst._currentElement._owner; - ReactControlledValuePropTypes.checkPropTypes( - 'input', - props, - owner ? owner.getName() : null, - ); + ReactControlledValuePropTypes.checkPropTypes('input', props, () => + getStackAddendumByID(inst._debugID)); if ( props.checked !== undefined && diff --git a/src/renderers/dom/stack/client/wrappers/ReactDOMSelect.js b/src/renderers/dom/stack/client/wrappers/ReactDOMSelect.js index efc98b4134..1d8bbb9721 100644 --- a/src/renderers/dom/stack/client/wrappers/ReactDOMSelect.js +++ b/src/renderers/dom/stack/client/wrappers/ReactDOMSelect.js @@ -16,6 +16,12 @@ var ReactDOMComponentTree = require('ReactDOMComponentTree'); var warning = require('fbjs/lib/warning'); +if (__DEV__) { + var { + getStackAddendumByID, + } = require('ReactGlobalSharedState').ReactComponentTreeHook; +} + var didWarnValueDefaultValue = false; function getDeclarationErrorAddendum(owner) { @@ -36,11 +42,8 @@ var valuePropNames = ['value', 'defaultValue']; */ function checkSelectPropTypes(inst, props) { var owner = inst._currentElement._owner; - ReactControlledValuePropTypes.checkPropTypes( - 'select', - props, - owner ? owner.getName() : null, - ); + ReactControlledValuePropTypes.checkPropTypes('select', props, () => + getStackAddendumByID(inst._debugID)); for (var i = 0; i < valuePropNames.length; i++) { var propName = valuePropNames[i]; diff --git a/src/renderers/dom/stack/client/wrappers/ReactDOMTextarea.js b/src/renderers/dom/stack/client/wrappers/ReactDOMTextarea.js index 4ddf9e51a8..4f20530b4e 100644 --- a/src/renderers/dom/stack/client/wrappers/ReactDOMTextarea.js +++ b/src/renderers/dom/stack/client/wrappers/ReactDOMTextarea.js @@ -17,6 +17,12 @@ var ReactDOMComponentTree = require('ReactDOMComponentTree'); var invariant = require('fbjs/lib/invariant'); var warning = require('fbjs/lib/warning'); +if (__DEV__) { + var { + getStackAddendumByID, + } = require('ReactGlobalSharedState').ReactComponentTreeHook; +} + var didWarnValDefaultVal = false; /** @@ -57,12 +63,8 @@ var ReactDOMTextarea = { mountWrapper: function(inst, props) { if (__DEV__) { - var owner = inst._currentElement._owner; - ReactControlledValuePropTypes.checkPropTypes( - 'textarea', - props, - owner ? owner.getName() : null, - ); + ReactControlledValuePropTypes.checkPropTypes('textarea', props, () => + getStackAddendumByID(inst._debugID)); if ( props.value !== undefined && props.defaultValue !== undefined &&