From 0c10b5edf04f8d6cbd23718ecc823089a20002ba Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Fri, 3 Apr 2020 21:25:04 -0700 Subject: [PATCH] Don't use checkPropTypes for internals We use console.error for internal warnings. --- .../src/__tests__/ReactDOMInput-test.js | 14 ++-- .../react-dom/src/client/ReactDOMInput.js | 4 +- .../react-dom/src/client/ReactDOMSelect.js | 4 +- .../react-dom/src/client/ReactDOMTextarea.js | 4 +- .../src/server/ReactPartialRenderer.js | 8 +- .../shared/ReactControlledValuePropTypes.js | 82 +++++++------------ 6 files changed, 46 insertions(+), 70 deletions(-) diff --git a/packages/react-dom/src/__tests__/ReactDOMInput-test.js b/packages/react-dom/src/__tests__/ReactDOMInput-test.js index 7c36518857dae..98be58fa29575 100644 --- a/packages/react-dom/src/__tests__/ReactDOMInput-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMInput-test.js @@ -54,7 +54,7 @@ describe('ReactDOMInput', () => { expect(() => { ReactDOM.render(, container); }).toErrorDev( - 'Failed prop type: You provided a `value` prop to a form field without an `onChange` handler.', + 'Warning: You provided a `value` prop to a form field without an `onChange` handler.', ); }); @@ -62,7 +62,7 @@ describe('ReactDOMInput', () => { expect(() => { ReactDOM.render(, container); }).toErrorDev( - 'Failed prop type: You provided a `value` prop to a form field without an `onChange` handler.', + 'Warning: You provided a `value` prop to a form field without an `onChange` handler.', ); }); @@ -70,7 +70,7 @@ describe('ReactDOMInput', () => { expect(() => { ReactDOM.render(, container); }).toErrorDev( - 'Failed prop type: You provided a `value` prop to a form field without an `onChange` handler.', + 'Warning: You provided a `value` prop to a form field without an `onChange` handler.', ); }); @@ -78,7 +78,7 @@ describe('ReactDOMInput', () => { expect(() => ReactDOM.render(, container), ).toErrorDev( - 'Failed prop type: You provided a `checked` prop to a form field without an `onChange` handler.', + 'Warning: You provided a `checked` prop to a form field without an `onChange` handler.', ); }); @@ -95,7 +95,7 @@ describe('ReactDOMInput', () => { container, ), ).toErrorDev( - 'Failed prop type: You provided a `checked` prop to a form field without an `onChange` handler. ' + + 'Warning: You provided a `checked` prop to a form field without an `onChange` handler. ' + 'This will render a read-only field. If the field should be mutable use `defaultChecked`. ' + 'Otherwise, set either `onChange` or `readOnly`.', ); @@ -125,7 +125,7 @@ describe('ReactDOMInput', () => { expect(() => { node = ReactDOM.render(, container); }).toErrorDev( - 'Failed prop type: You provided a `value` prop to a form field without an `onChange` handler.', + 'Warning: You provided a `value` prop to a form field without an `onChange` handler.', ); setUntrackedValue.call(node, 'giraffe'); @@ -1172,7 +1172,7 @@ describe('ReactDOMInput', () => { container, ), ).toErrorDev( - 'Warning: Failed prop type: You provided a `value` prop to a form ' + + 'Warning: 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' + diff --git a/packages/react-dom/src/client/ReactDOMInput.js b/packages/react-dom/src/client/ReactDOMInput.js index 884c2ad9dfe2f..93e263c5d3159 100644 --- a/packages/react-dom/src/client/ReactDOMInput.js +++ b/packages/react-dom/src/client/ReactDOMInput.js @@ -14,7 +14,7 @@ import invariant from 'shared/invariant'; import {setValueForProperty} from './DOMPropertyOperations'; import {getFiberCurrentPropsFromNode} from './ReactDOMComponentTree'; import {getToStringValue, toString} from './ToStringValue'; -import ReactControlledValuePropTypes from '../shared/ReactControlledValuePropTypes'; +import {checkControlledValueProps} from '../shared/ReactControlledValuePropTypes'; import {updateValueIfChanged} from './inputValueTracking'; import {disableInputAttributeSyncing} from 'shared/ReactFeatureFlags'; @@ -73,7 +73,7 @@ export function getHostProps(element: Element, props: Object) { export function initWrapperState(element: Element, props: Object) { if (__DEV__) { - ReactControlledValuePropTypes.checkPropTypes('input', props); + checkControlledValueProps('input', props); if ( props.checked !== undefined && diff --git a/packages/react-dom/src/client/ReactDOMSelect.js b/packages/react-dom/src/client/ReactDOMSelect.js index 0a8b179fe0ff2..d97e01be0ab60 100644 --- a/packages/react-dom/src/client/ReactDOMSelect.js +++ b/packages/react-dom/src/client/ReactDOMSelect.js @@ -10,7 +10,7 @@ // TODO: direct imports like some-package/src/* are bad. Fix me. import {getCurrentFiberOwnerNameInDevOrNull} from 'react-reconciler/src/ReactCurrentFiber'; -import ReactControlledValuePropTypes from '../shared/ReactControlledValuePropTypes'; +import {checkControlledValueProps} from '../shared/ReactControlledValuePropTypes'; import {getToStringValue, toString} from './ToStringValue'; let didWarnValueDefaultValue; @@ -38,7 +38,7 @@ const valuePropNames = ['value', 'defaultValue']; */ function checkSelectPropTypes(props) { if (__DEV__) { - ReactControlledValuePropTypes.checkPropTypes('select', props); + checkControlledValueProps('select', props); for (let i = 0; i < valuePropNames.length; i++) { const propName = valuePropNames[i]; diff --git a/packages/react-dom/src/client/ReactDOMTextarea.js b/packages/react-dom/src/client/ReactDOMTextarea.js index 9c1505bac6345..a37c36b94efd8 100644 --- a/packages/react-dom/src/client/ReactDOMTextarea.js +++ b/packages/react-dom/src/client/ReactDOMTextarea.js @@ -9,7 +9,7 @@ import invariant from 'shared/invariant'; -import ReactControlledValuePropTypes from '../shared/ReactControlledValuePropTypes'; +import {checkControlledValueProps} from '../shared/ReactControlledValuePropTypes'; import {getCurrentFiberOwnerNameInDevOrNull} from 'react-reconciler/src/ReactCurrentFiber'; import {getToStringValue, toString} from './ToStringValue'; import type {ToStringValue} from './ToStringValue'; @@ -64,7 +64,7 @@ export function getHostProps(element: Element, props: Object) { export function initWrapperState(element: Element, props: Object) { const node = ((element: any): TextAreaWithWrapperState); if (__DEV__) { - ReactControlledValuePropTypes.checkPropTypes('textarea', props); + checkControlledValueProps('textarea', props); if ( props.value !== undefined && props.defaultValue !== undefined && diff --git a/packages/react-dom/src/server/ReactPartialRenderer.js b/packages/react-dom/src/server/ReactPartialRenderer.js index d0dcd435f1799..4393208f27055 100644 --- a/packages/react-dom/src/server/ReactPartialRenderer.js +++ b/packages/react-dom/src/server/ReactPartialRenderer.js @@ -67,7 +67,7 @@ import { getIntrinsicNamespace, getChildNamespace, } from '../shared/DOMNamespaces'; -import ReactControlledValuePropTypes from '../shared/ReactControlledValuePropTypes'; +import {checkControlledValueProps} from '../shared/ReactControlledValuePropTypes'; import assertValidProps from '../shared/assertValidProps'; import dangerousStyleValue from '../shared/dangerousStyleValue'; import hyphenateStyleName from '../shared/hyphenateStyleName'; @@ -1358,7 +1358,7 @@ class ReactDOMServerRenderer { let props = element.props; if (tag === 'input') { if (__DEV__) { - ReactControlledValuePropTypes.checkPropTypes('input', props); + checkControlledValueProps('input', props); if ( props.checked !== undefined && @@ -1410,7 +1410,7 @@ class ReactDOMServerRenderer { ); } else if (tag === 'textarea') { if (__DEV__) { - ReactControlledValuePropTypes.checkPropTypes('textarea', props); + checkControlledValueProps('textarea', props); if ( props.value !== undefined && props.defaultValue !== undefined && @@ -1465,7 +1465,7 @@ class ReactDOMServerRenderer { }); } else if (tag === 'select') { if (__DEV__) { - ReactControlledValuePropTypes.checkPropTypes('select', props); + checkControlledValueProps('select', props); for (let i = 0; i < valuePropNames.length; i++) { const propName = valuePropNames[i]; diff --git a/packages/react-dom/src/shared/ReactControlledValuePropTypes.js b/packages/react-dom/src/shared/ReactControlledValuePropTypes.js index 60df6ab2e558f..c15c4a94aaecf 100644 --- a/packages/react-dom/src/shared/ReactControlledValuePropTypes.js +++ b/packages/react-dom/src/shared/ReactControlledValuePropTypes.js @@ -5,81 +5,57 @@ * LICENSE file in the root directory of this source tree. */ -import checkPropTypes from 'shared/checkPropTypes'; -import ReactSharedInternals from 'shared/ReactSharedInternals'; import {enableDeprecatedFlareAPI} from 'shared/ReactFeatureFlags'; -let ReactDebugCurrentFrame = null; - -const ReactControlledValuePropTypes = { - checkPropTypes: null, +const hasReadOnlyValue = { + button: true, + checkbox: true, + image: true, + hidden: true, + radio: true, + reset: true, + submit: true, }; -if (__DEV__) { - ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - - const hasReadOnlyValue = { - button: true, - checkbox: true, - image: true, - hidden: true, - radio: true, - reset: true, - submit: true, - }; - - const propTypes = { - value: function(props, propName, componentName) { - if ( +export function checkControlledValueProps( + tagName: string, + props: Object, +): void { + if (__DEV__) { + if ( + !( hasReadOnlyValue[props.type] || props.onChange || props.onInput || props.readOnly || props.disabled || - props[propName] == null || + props.value == null || (enableDeprecatedFlareAPI && props.DEPRECATED_flareListeners) - ) { - return null; - } - return new Error( + ) + ) { + console.error( '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`.', ); - }, - checked: function(props, propName, componentName) { - if ( + } + + if ( + !( props.onChange || props.readOnly || props.disabled || - props[propName] == null || + props.checked == null || (enableDeprecatedFlareAPI && props.DEPRECATED_flareListeners) - ) { - return null; - } - return new Error( + ) + ) { + console.error( 'You provided a `checked` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultChecked`. Otherwise, ' + 'set either `onChange` or `readOnly`.', ); - }, - }; - - /** - * Provide a linked `value` attribute for controlled forms. You should not use - * this outside of the ReactDOM controlled form components. - */ - ReactControlledValuePropTypes.checkPropTypes = function(tagName, props) { - checkPropTypes( - propTypes, - props, - 'prop', - tagName, - ReactDebugCurrentFrame.getStackAddendum, - ); - }; + } + } } - -export default ReactControlledValuePropTypes;