informed
Version:
A lightweight framework and utility for building powerful forms in React applications
121 lines (112 loc) • 4.75 kB
JavaScript
import { slicedToArray as _slicedToArray, toConsumableArray as _toConsumableArray } from '../_virtual/_rollupPluginBabelHelpers.js';
import { useContext, useRef, useMemo, useEffect } from 'react';
import { ScopeContext } from '../Context.js';
import { useFormController } from './useFormController.js';
import { useStateWithGetter } from './useStateWithGetter.js';
import { useFieldSubscription } from './useFieldSubscription.js';
import { Debug } from '../debug.js';
var logger = Debug('informed:useRelevance' + '\t');
/* ----------------------- useRelevance ----------------------- */
var useRelevance = function useRelevance(_ref) {
var name = _ref.name,
relevant = _ref.relevant,
_ref$relevanceWhen = _ref.relevanceWhen,
relevanceWhen = _ref$relevanceWhen === void 0 ? [] : _ref$relevanceWhen,
_ref$relevanceDeps = _ref.relevanceDeps,
relevanceDeps = _ref$relevanceDeps === void 0 ? [] : _ref$relevanceDeps;
// Grab the form controller
var formController = useFormController();
// Get scope
var scope = useContext(ScopeContext);
// Need ref to scope because subscriptions will keep ref to it
var scopeRef = useRef(scope);
scopeRef.current = scope;
var depsRef = useRef();
depsRef.current = relevanceDeps;
// Relevant state
var _useStateWithGetter = useStateWithGetter(function () {
if (relevant) {
logger("re-evaluated relevance for ".concat(name, " for the first inital load"));
return relevant({
formState: formController.getFormState(),
formApi: formController.getFormApi(),
scope: scope,
relevanceDeps: relevanceDeps
});
}
return true;
}),
_useStateWithGetter2 = _slicedToArray(_useStateWithGetter, 3),
isRelevant = _useStateWithGetter2[0],
setIsRelevant = _useStateWithGetter2[1],
getIsRelevant = _useStateWithGetter2[2];
var check = typeof relevanceWhen === 'function' ? [] : relevanceWhen;
var fields = useMemo(function () {
if (typeof relevanceWhen === 'function') {
// Generate fields array with scope
// Example: relevanceWhen = scope => [`${scope}.foo`, `${scope}.bar`]
return relevanceWhen(scope);
}
// Example relevanceWhen = ["name", "age"]
return relevanceWhen;
}, [].concat(_toConsumableArray(check), [scope]));
// Example relevanceWhen = ["name", "age"]
useFieldSubscription('field-value', fields, function (target) {
logger("re-evaluating relevance for ".concat(name, " because of ").concat(target));
var rel = relevant({
formState: formController.getFormState(),
formApi: formController.getFormApi(),
scope: scopeRef.current,
relevanceDeps: depsRef.current
});
// Only update if we changed
if (getIsRelevant() != rel) {
// console.log("UPDATING", name, rel);
setIsRelevant(rel);
}
},
// Note: we pass false because we don't want this to be scoped!
// When the user explicitly uses a function!
!(typeof relevanceWhen === 'function'));
// Register for ALL events if we have no relevanceWhen
useEffect(function () {
if (relevant && typeof relevanceWhen !== 'function' && relevanceWhen.length === 0) {
// When we have a field update we always check
var listener = function listener(target) {
logger("re-evaluating relevance for ".concat(name, " because of ").concat(target));
var rel = relevant({
formState: formController.getFormState(),
formApi: formController.getFormApi(),
scope: scopeRef.current,
relevanceDeps: depsRef.current
});
logger("re-evaluated relevance for ".concat(name, " because of ").concat(target, " and got ").concat(rel));
// Only update if we changed
if (getIsRelevant() != rel) {
// console.log("UPDATING", name, rel);
logger("updating relevance for ".concat(name, " because of ").concat(target, " and got ").concat(rel));
setIsRelevant(rel);
}
};
formController.emitter.on('field', listener);
return function () {
// console.log("REMOVED LISTENER", name);
formController.emitter.removeListener('field', listener);
};
}
}, []);
useEffect(function () {
if (relevant) {
logger("re-evaluated relevance for ".concat(name, " because name change or relevanceDeps"));
// When name changes we always check if relevant
setIsRelevant(relevant({
formState: formController.getFormState(),
formApi: formController.getFormApi(),
scope: scopeRef.current,
relevanceDeps: depsRef.current
}));
}
}, [name].concat(_toConsumableArray(relevanceDeps)));
return isRelevant;
};
export { useRelevance };