@uifabric/utilities
Version:
Fluent UI React utilities for building components.
73 lines • 4.6 kB
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 '" + valueProp + "' prop to a " + componentName + " without an '" + onChangeProp + "' handler. " +
("This will render a read-only field. If the field should be mutable use '" + defaultValueProp + "'. ") +
("Otherwise, set '" + onChangeProp + "'" + (readOnlyProp ? " or '" + 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 '" + valueProp + "' and '" + defaultValueProp + "' to a " + componentName + ". " +
("Form fields must be either controlled or uncontrolled (specify either the '" + valueProp + "' prop, ") +
("or the '" + defaultValueProp + "' prop, but not both). Decide between using a controlled or uncontrolled ") +
(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 " + oldType + " " + componentName + " to be " + newType + ". " +
(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