@atlaskit/form
Version:
A form allows people to input information.
76 lines (71 loc) • 3.18 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useFormState = void 0;
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _react = require("react");
var _form = require("./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.
*/
var useFormState = exports.useFormState = function useFormState() {
var subscriptionConfig = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultSubscriptionConfig;
var _useContext = (0, _react.useContext)(_form.FormContext),
subscribe = _useContext.subscribe;
var _useState = (0, _react.useState)(),
_useState2 = (0, _slicedToArray2.default)(_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 = (0, _react.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 = (0, _react.useMemo)(function () {
return subscriptionConfig;
},
// eslint-disable-next-line react-hooks/exhaustive-deps -- intentionally controlled with a hash to have an explicit shallow comparison
[subscriptionConfigHash]);
(0, _react.useEffect)(function () {
var unsubscribe = subscribe(function (formState) {
setState(formState);
}, config);
return function () {
return unsubscribe();
};
}, [subscribe, config]);
return state;
};