Skip to content

Commit

Permalink
Don't use checkPropTypes for internals (#18488)
Browse files Browse the repository at this point in the history
We use console.error for internal warnings.
  • Loading branch information
sebmarkbage committed Apr 4, 2020
1 parent 2ff27ec commit 1fd4543
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 70 deletions.
14 changes: 7 additions & 7 deletions packages/react-dom/src/__tests__/ReactDOMInput-test.js
Expand Up @@ -54,31 +54,31 @@ describe('ReactDOMInput', () => {
expect(() => {
ReactDOM.render(<input type="text" value={0} />, 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.',
);
});

it('should warn for controlled value of "" with missing onChange', () => {
expect(() => {
ReactDOM.render(<input type="text" value="" />, 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.',
);
});

it('should warn for controlled value of "0" with missing onChange', () => {
expect(() => {
ReactDOM.render(<input type="text" value="0" />, 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.',
);
});

it('should warn for controlled value of false with missing onChange', () => {
expect(() =>
ReactDOM.render(<input type="checkbox" checked={false} />, 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.',
);
});

Expand All @@ -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`.',
);
Expand Down Expand Up @@ -125,7 +125,7 @@ describe('ReactDOMInput', () => {
expect(() => {
node = ReactDOM.render(<input type="text" value="lion" />, 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');
Expand Down Expand Up @@ -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' +
Expand Down
4 changes: 2 additions & 2 deletions packages/react-dom/src/client/ReactDOMInput.js
Expand Up @@ -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';

Expand Down Expand Up @@ -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 &&
Expand Down
4 changes: 2 additions & 2 deletions packages/react-dom/src/client/ReactDOMSelect.js
Expand Up @@ -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;
Expand Down Expand Up @@ -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];
Expand Down
4 changes: 2 additions & 2 deletions packages/react-dom/src/client/ReactDOMTextarea.js
Expand Up @@ -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';
Expand Down Expand Up @@ -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 &&
Expand Down
8 changes: 4 additions & 4 deletions packages/react-dom/src/server/ReactPartialRenderer.js
Expand Up @@ -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';
Expand Down Expand Up @@ -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 &&
Expand Down Expand Up @@ -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 &&
Expand Down Expand Up @@ -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];
Expand Down
82 changes: 29 additions & 53 deletions packages/react-dom/src/shared/ReactControlledValuePropTypes.js
Expand Up @@ -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;

0 comments on commit 1fd4543

Please sign in to comment.