From ebcc9913e31d53ce609f14e2abade7e5e268ad87 Mon Sep 17 00:00:00 2001 From: emyarod Date: Thu, 29 Aug 2019 10:43:32 -0500 Subject: [PATCH] chore: use controlled state with value refs: https://github.com/carbon-design-system/carbon/pull/3028 --- src/internal/FeatureFlags.js | 29 +++++++++++++++++++++++++ src/prop-types/requiredIfValueExists.js | 26 ++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 src/prop-types/requiredIfValueExists.js diff --git a/src/internal/FeatureFlags.js b/src/internal/FeatureFlags.js index 2c5c8998ce..7339f07468 100644 --- a/src/internal/FeatureFlags.js +++ b/src/internal/FeatureFlags.js @@ -31,3 +31,32 @@ export const componentsX = false; * Support for prop -> state sync of `` value. */ export const sliderValuePropSync = breakingChangesX; + +/** + * With this flag, certain components will be created in either a controlled or controlled + * mode based on the existence of a value prop. + * + * The following components will have the significance of their props slightly altered as outlined below. + * + * Components: `` + * + * * `value` → when provided, enables controlled mode. + * For the rest of the component's lifecycle, it will be controlled by this prop as it's single source of truth. + * * `defaultValue` → Optional starting value, used for for uncontrolled mode only (no value prop). + * The value prop takes precedence over defaultValue. + * * `onChange` → Optional event handler. + * However, if value is provided and a handler is not, we'll throw a warning indicating the component is now read-only + * * `readOnly` → silences the above warning, acknowledging the read-only state of the component + * + * This flag also disables prop -> state sync in several components, notablly ``. + * + * This flag also updates event handlers to pass an up-to-date value in the second parameter, + * so applications can use it in both controlled and uncontrolled components. + * + * * _With_ this feature flag, the signature of the event handler will be altered to provide additional context in the second parameter: `onChange(event, { value, ...rest })` where: + * * `event` is the (React) raw event + * * `value` is the new value + * * `rest` tells you additional information based on the source component + * * _Without_ this feature flag the event handler has component-specific signature, e.g. `onChange(event, direction)`. + */ +export const useControlledStateWithValue = false; diff --git a/src/prop-types/requiredIfValueExists.js b/src/prop-types/requiredIfValueExists.js new file mode 100644 index 0000000000..2d1ad9c7c7 --- /dev/null +++ b/src/prop-types/requiredIfValueExists.js @@ -0,0 +1,26 @@ +/** + * Copyright IBM Corp. 2016, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +/** + * @param {Function} propType The original prop type checker. + * @returns {Function} The new prop type checker for `onChange` that makes it required if `value` exists and `readOnly` does not exist. + */ +export default function requiredIfValueExists(propType) { + return function check(props, propName, componentName, ...rest) { + const { [propName]: onChange, value, readOnly } = props; + const exists = onChange !== undefined; + const valueExists = value !== undefined; + if (__DEV__ && !exists && valueExists && !readOnly) { + return new Error( + `You provided a value prop to \`${componentName}\` 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`.' + ); + } + return propType(props, propName, componentName, ...rest); + }; +}