73 lines
4.6 KiB
JavaScript
73 lines
4.6 KiB
JavaScript
import { warn } from './warn';
|
|
import { isControlled as checkIsControlled } from '../controlled';
|
|
var warningsMap;
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
warningsMap = {
|
|
valueOnChange: {},
|
|
valueDefaultValue: {},
|
|
controlledToUncontrolled: {},
|
|
uncontrolledToControlled: {},
|
|
};
|
|
}
|
|
/** Reset controlled usage warnings for testing purposes. */
|
|
export function resetControlledWarnings() {
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
warningsMap.valueOnChange = {};
|
|
warningsMap.valueDefaultValue = {};
|
|
warningsMap.controlledToUncontrolled = {};
|
|
warningsMap.uncontrolledToControlled = {};
|
|
}
|
|
}
|
|
/**
|
|
* Check for and warn on the following error conditions with a form component:
|
|
* - A value prop is provided (indicated it's being used as controlled) without a change handler,
|
|
* and the component is not read-only
|
|
* - Both the value and defaultValue props are provided
|
|
* - The component is attempting to switch between controlled and uncontrolled
|
|
*
|
|
* The messages mimic the warnings React gives for these error conditions on input elements.
|
|
* The warning will only be displayed once per component ID.
|
|
*/
|
|
export function warnControlledUsage(params) {
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
var componentId = params.componentId, componentName = params.componentName, defaultValueProp = params.defaultValueProp, props = params.props, oldProps = params.oldProps, onChangeProp = params.onChangeProp, readOnlyProp = params.readOnlyProp, valueProp = params.valueProp;
|
|
// This warning logic closely follows what React does for native <input> elements.
|
|
var oldIsControlled = oldProps ? checkIsControlled(oldProps, valueProp) : undefined;
|
|
var newIsControlled = checkIsControlled(props, valueProp);
|
|
if (newIsControlled) {
|
|
// onChange (or readOnly) must be provided if value is provided
|
|
var hasOnChange = !!props[onChangeProp];
|
|
var isReadOnly = !!(readOnlyProp && props[readOnlyProp]);
|
|
if (!(hasOnChange || isReadOnly) && !warningsMap.valueOnChange[componentId]) {
|
|
warningsMap.valueOnChange[componentId] = true;
|
|
warn("Warning: You provided a '".concat(String(valueProp), "' prop to a ").concat(String(componentName), " without an '").concat(String(onChangeProp), "' handler. ") +
|
|
"This will render a read-only field. If the field should be mutable use '".concat(String(defaultValueProp), "'. ") +
|
|
"Otherwise, set '".concat(String(onChangeProp), "'").concat(readOnlyProp ? " or '".concat(String(readOnlyProp), "'") : '', "."));
|
|
}
|
|
// value and defaultValue are mutually exclusive
|
|
var defaultValue = props[defaultValueProp];
|
|
if (defaultValue !== undefined && defaultValue !== null && !warningsMap.valueDefaultValue[componentId]) {
|
|
warningsMap.valueDefaultValue[componentId] = true;
|
|
warn("Warning: You provided both '".concat(String(valueProp), "' and '").concat(String(defaultValueProp), "' to a ").concat(componentName, ". ") +
|
|
"Form fields must be either controlled or uncontrolled (specify either the '".concat(String(valueProp), "' prop, ") +
|
|
"or the '".concat(String(defaultValueProp), "' prop, but not both). Decide between using a controlled or uncontrolled ") +
|
|
"".concat(componentName, " and remove one of these props. More info: https://fb.me/react-controlled-components"));
|
|
}
|
|
}
|
|
// Warn if switching between uncontrolled and controlled. (One difference between this implementation
|
|
// and React's <input> is that if oldIsControlled is indeterminate and newIsControlled true, we don't warn.)
|
|
if (oldProps && newIsControlled !== oldIsControlled) {
|
|
var oldType = oldIsControlled ? 'a controlled' : 'an uncontrolled';
|
|
var newType = oldIsControlled ? 'uncontrolled' : 'controlled';
|
|
var warnMap = oldIsControlled ? warningsMap.controlledToUncontrolled : warningsMap.uncontrolledToControlled;
|
|
if (!warnMap[componentId]) {
|
|
warnMap[componentId] = true;
|
|
warn("Warning: A component is changing ".concat(oldType, " ").concat(componentName, " to be ").concat(newType, ". ") +
|
|
"".concat(componentName, "s should not switch from controlled to uncontrolled (or vice versa). ") +
|
|
"Decide between using controlled or uncontrolled for the lifetime of the component. " +
|
|
"More info: https://fb.me/react-controlled-components");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//# sourceMappingURL=warnControlledUsage.js.map
|