~useWatch.js 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
  2. import warning from "rc-util/es/warning";
  3. import FieldContext, { HOOK_MARK } from "./FieldContext";
  4. import { useState, useContext, useEffect, useRef, useMemo } from 'react';
  5. import { getNamePath, getValue } from "./utils/valueUtil";
  6. import { isFormInstance } from "./utils/typeUtil";
  7. export function stringify(value) {
  8. try {
  9. return JSON.stringify(value);
  10. } catch (err) {
  11. return Math.random();
  12. }
  13. }
  14. var useWatchWarning = process.env.NODE_ENV !== 'production' ? function (namePath) {
  15. var fullyStr = namePath.join('__RC_FIELD_FORM_SPLIT__');
  16. var nameStrRef = useRef(fullyStr);
  17. warning(nameStrRef.current === fullyStr, '`useWatch` is not support dynamic `namePath`. Please provide static instead.');
  18. } : function () {};
  19. function useWatch() {
  20. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  21. args[_key] = arguments[_key];
  22. }
  23. var _args$ = args[0],
  24. dependencies = _args$ === void 0 ? [] : _args$,
  25. _args$2 = args[1],
  26. _form = _args$2 === void 0 ? {} : _args$2;
  27. var options = isFormInstance(_form) ? {
  28. form: _form
  29. } : _form;
  30. var form = options.form;
  31. var _useState = useState(),
  32. _useState2 = _slicedToArray(_useState, 2),
  33. value = _useState2[0],
  34. setValue = _useState2[1];
  35. var valueStr = useMemo(function () {
  36. return stringify(value);
  37. }, [value]);
  38. var valueStrRef = useRef(valueStr);
  39. valueStrRef.current = valueStr;
  40. var fieldContext = useContext(FieldContext);
  41. var formInstance = form || fieldContext;
  42. var isValidForm = formInstance && formInstance._init;
  43. // Warning if not exist form instance
  44. if (process.env.NODE_ENV !== 'production') {
  45. warning(args.length === 2 ? form ? isValidForm : true : isValidForm, 'useWatch requires a form instance since it can not auto detect from context.');
  46. }
  47. var namePath = getNamePath(dependencies);
  48. var namePathRef = useRef(namePath);
  49. namePathRef.current = namePath;
  50. useWatchWarning(namePath);
  51. useEffect(function () {
  52. // Skip if not exist form instance
  53. if (!isValidForm) {
  54. return;
  55. }
  56. var getFieldsValue = formInstance.getFieldsValue,
  57. getInternalHooks = formInstance.getInternalHooks;
  58. var _getInternalHooks = getInternalHooks(HOOK_MARK),
  59. registerWatch = _getInternalHooks.registerWatch;
  60. var cancelRegister = registerWatch(function (values, allValues) {
  61. var newValue = getValue(options.preserve ? allValues : values, namePathRef.current);
  62. var nextValueStr = stringify(newValue);
  63. // Compare stringify in case it's nest object
  64. if (valueStrRef.current !== nextValueStr) {
  65. valueStrRef.current = nextValueStr;
  66. setValue(newValue);
  67. }
  68. });
  69. // TODO: We can improve this perf in future
  70. var initialValue = getValue(options.preserve ? getFieldsValue(true) : getFieldsValue(), namePathRef.current);
  71. setValue(initialValue);
  72. return cancelRegister;
  73. },
  74. // We do not need re-register since namePath content is the same
  75. // eslint-disable-next-line react-hooks/exhaustive-deps
  76. [isValidForm]);
  77. return value;
  78. }
  79. export default useWatch;