useMergedState.js 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
  2. import useEvent from "./useEvent";
  3. import { useLayoutUpdateEffect } from "./useLayoutEffect";
  4. import useState from "./useState";
  5. /** We only think `undefined` is empty */
  6. function hasValue(value) {
  7. return value !== undefined;
  8. }
  9. /**
  10. * Similar to `useState` but will use props value if provided.
  11. * Note that internal use rc-util `useState` hook.
  12. */
  13. export default function useMergedState(defaultStateValue, option) {
  14. var _ref = option || {},
  15. defaultValue = _ref.defaultValue,
  16. value = _ref.value,
  17. onChange = _ref.onChange,
  18. postState = _ref.postState;
  19. // ======================= Init =======================
  20. var _useState = useState(function () {
  21. if (hasValue(value)) {
  22. return value;
  23. } else if (hasValue(defaultValue)) {
  24. return typeof defaultValue === 'function' ? defaultValue() : defaultValue;
  25. } else {
  26. return typeof defaultStateValue === 'function' ? defaultStateValue() : defaultStateValue;
  27. }
  28. }),
  29. _useState2 = _slicedToArray(_useState, 2),
  30. innerValue = _useState2[0],
  31. setInnerValue = _useState2[1];
  32. var mergedValue = value !== undefined ? value : innerValue;
  33. var postMergedValue = postState ? postState(mergedValue) : mergedValue;
  34. // ====================== Change ======================
  35. var onChangeFn = useEvent(onChange);
  36. var _useState3 = useState([mergedValue]),
  37. _useState4 = _slicedToArray(_useState3, 2),
  38. prevValue = _useState4[0],
  39. setPrevValue = _useState4[1];
  40. useLayoutUpdateEffect(function () {
  41. var prev = prevValue[0];
  42. if (innerValue !== prev) {
  43. onChangeFn(innerValue, prev);
  44. }
  45. }, [prevValue]);
  46. // Sync value back to `undefined` when it from control to un-control
  47. useLayoutUpdateEffect(function () {
  48. if (!hasValue(value)) {
  49. setInnerValue(value);
  50. }
  51. }, [value]);
  52. // ====================== Update ======================
  53. var triggerChange = useEvent(function (updater, ignoreDestroy) {
  54. setInnerValue(updater, ignoreDestroy);
  55. setPrevValue([mergedValue], ignoreDestroy);
  56. });
  57. return [postMergedValue, triggerChange];
  58. }