useWatch.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. "use strict";
  2. var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
  3. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
  4. Object.defineProperty(exports, "__esModule", {
  5. value: true
  6. });
  7. exports.default = void 0;
  8. exports.stringify = stringify;
  9. var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
  10. var _warning = _interopRequireDefault(require("rc-util/lib/warning"));
  11. var _react = require("react");
  12. var _FieldContext = _interopRequireWildcard(require("./FieldContext"));
  13. var _typeUtil = require("./utils/typeUtil");
  14. var _valueUtil = require("./utils/valueUtil");
  15. function stringify(value) {
  16. try {
  17. return JSON.stringify(value);
  18. } catch (err) {
  19. return Math.random();
  20. }
  21. }
  22. var useWatchWarning = process.env.NODE_ENV !== 'production' ? function (namePath) {
  23. var fullyStr = namePath.join('__RC_FIELD_FORM_SPLIT__');
  24. var nameStrRef = (0, _react.useRef)(fullyStr);
  25. (0, _warning.default)(nameStrRef.current === fullyStr, '`useWatch` is not support dynamic `namePath`. Please provide static instead.');
  26. } : function () {};
  27. // ------- selector type -------
  28. // ------- selector type end -------
  29. function useWatch() {
  30. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  31. args[_key] = arguments[_key];
  32. }
  33. var dependencies = args[0],
  34. _args$ = args[1],
  35. _form = _args$ === void 0 ? {} : _args$;
  36. var options = (0, _typeUtil.isFormInstance)(_form) ? {
  37. form: _form
  38. } : _form;
  39. var form = options.form;
  40. var _useState = (0, _react.useState)(),
  41. _useState2 = (0, _slicedToArray2.default)(_useState, 2),
  42. value = _useState2[0],
  43. setValue = _useState2[1];
  44. var valueStr = (0, _react.useMemo)(function () {
  45. return stringify(value);
  46. }, [value]);
  47. var valueStrRef = (0, _react.useRef)(valueStr);
  48. valueStrRef.current = valueStr;
  49. var fieldContext = (0, _react.useContext)(_FieldContext.default);
  50. var formInstance = form || fieldContext;
  51. var isValidForm = formInstance && formInstance._init;
  52. // Warning if not exist form instance
  53. if (process.env.NODE_ENV !== 'production') {
  54. (0, _warning.default)(args.length === 2 ? form ? isValidForm : true : isValidForm, 'useWatch requires a form instance since it can not auto detect from context.');
  55. }
  56. var namePath = (0, _valueUtil.getNamePath)(dependencies);
  57. var namePathRef = (0, _react.useRef)(namePath);
  58. namePathRef.current = namePath;
  59. useWatchWarning(namePath);
  60. (0, _react.useEffect)(function () {
  61. // Skip if not exist form instance
  62. if (!isValidForm) {
  63. return;
  64. }
  65. var getFieldsValue = formInstance.getFieldsValue,
  66. getInternalHooks = formInstance.getInternalHooks;
  67. var _getInternalHooks = getInternalHooks(_FieldContext.HOOK_MARK),
  68. registerWatch = _getInternalHooks.registerWatch;
  69. var getWatchValue = function getWatchValue(values, allValues) {
  70. var watchValue = options.preserve ? allValues : values;
  71. return typeof dependencies === 'function' ? dependencies(watchValue) : (0, _valueUtil.getValue)(watchValue, namePathRef.current);
  72. };
  73. var cancelRegister = registerWatch(function (values, allValues) {
  74. var newValue = getWatchValue(values, allValues);
  75. var nextValueStr = stringify(newValue);
  76. // Compare stringify in case it's nest object
  77. if (valueStrRef.current !== nextValueStr) {
  78. valueStrRef.current = nextValueStr;
  79. setValue(newValue);
  80. }
  81. });
  82. // TODO: We can improve this perf in future
  83. var initialValue = getWatchValue(getFieldsValue(), getFieldsValue(true));
  84. // React 18 has the bug that will queue update twice even the value is not changed
  85. // ref: https://github.com/facebook/react/issues/27213
  86. if (value !== initialValue) {
  87. setValue(initialValue);
  88. }
  89. return cancelRegister;
  90. },
  91. // We do not need re-register since namePath content is the same
  92. // eslint-disable-next-line react-hooks/exhaustive-deps
  93. [isValidForm]);
  94. return value;
  95. }
  96. var _default = exports.default = useWatch;