UNPKG

@atlaskit/form

Version:

A form allows people to input information.

70 lines (65 loc) 2.9 kB
import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import { useContext, useEffect, useMemo, useState } from 'react'; import { FormContext } from './form'; // Constantized to avoid a new object reference built every call var defaultSubscriptionConfig = { values: true }; /** * Build a simple hash for a given subscription object for use in a `useMemo` dependencies array. * This is because `{ values: true } !== { values: true }`, but `'values:true|' === 'values:true|'` * * @example { values: true, dirty: false } => 'values:true|dirty:false|' */ var getSubscriptionHash = function getSubscriptionHash(subscriptionConfig) { var hash = ''; for (var key in subscriptionConfig) { if (subscriptionConfig.hasOwnProperty(key)) { hash += "".concat(key, ":").concat(subscriptionConfig[key], "|"); } } return hash; }; /** * A hook to return a recent form state for use within the `<Form>` as it requires context access. * This is useful for previewing form state, or for building custom fields that need to react to form state. * * This should not be used as a way to persist form state into another form state, use `onSubmit` for proper form handling. * * @note On the initial render, this should be `undefined` as our form has not provided any state. */ export var useFormState = function useFormState() { var subscriptionConfig = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultSubscriptionConfig; var _useContext = useContext(FormContext), subscribe = _useContext.subscribe; var _useState = useState(), _useState2 = _slicedToArray(_useState, 2), state = _useState2[0], setState = _useState2[1]; /** * A hash for us to shallow compare the subscriptionConfig object to react to shallow changes, but avoid referential changes. * We avoid computing the hash if the subscription config has referential equality altogether. */ var subscriptionConfigHash = useMemo(function () { return getSubscriptionHash(subscriptionConfig); }, [subscriptionConfig]); /** * Return a memoized version of the subscription config to only react to shallow changes, not referential changes. * Eg. calling `useFormState({ values: true })` twice will result in two different objects by reference, but not by shallow comparison. * This will ensure we don't re-subscribe to the form state when the subscription config is the same. */ var config = useMemo(function () { return subscriptionConfig; }, // eslint-disable-next-line react-hooks/exhaustive-deps -- intentionally controlled with a hash to have an explicit shallow comparison [subscriptionConfigHash]); useEffect(function () { var unsubscribe = subscribe(function (formState) { setState(formState); }, config); return function () { return unsubscribe(); }; }, [subscribe, config]); return state; };