Immutable.js 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import _extends from "@babel/runtime/helpers/esm/extends";
  2. import { supportRef } from "rc-util/es/ref";
  3. import * as React from 'react';
  4. /**
  5. * Create Immutable pair for `makeImmutable` and `responseImmutable`.
  6. */
  7. export default function createImmutable() {
  8. var ImmutableContext = /*#__PURE__*/React.createContext(null);
  9. /**
  10. * Get render update mark by `makeImmutable` root.
  11. * Do not deps on the return value as render times
  12. * but only use for `useMemo` or `useCallback` deps.
  13. */
  14. function useImmutableMark() {
  15. return React.useContext(ImmutableContext);
  16. }
  17. /**
  18. * Wrapped Component will be marked as Immutable.
  19. * When Component parent trigger render,
  20. * it will notice children component (use with `responseImmutable`) node that parent has updated.
  21. * @param Component Passed Component
  22. * @param triggerRender Customize trigger `responseImmutable` children re-render logic. Default will always trigger re-render when this component re-render.
  23. */
  24. function makeImmutable(Component, shouldTriggerRender) {
  25. var refAble = supportRef(Component);
  26. var ImmutableComponent = function ImmutableComponent(props, ref) {
  27. var refProps = refAble ? {
  28. ref: ref
  29. } : {};
  30. var renderTimesRef = React.useRef(0);
  31. var prevProps = React.useRef(props);
  32. // If parent has the context, we do not wrap it
  33. var mark = useImmutableMark();
  34. if (mark !== null) {
  35. return /*#__PURE__*/React.createElement(Component, _extends({}, props, refProps));
  36. }
  37. if (
  38. // Always trigger re-render if not provide `notTriggerRender`
  39. !shouldTriggerRender || shouldTriggerRender(prevProps.current, props)) {
  40. renderTimesRef.current += 1;
  41. }
  42. prevProps.current = props;
  43. return /*#__PURE__*/React.createElement(ImmutableContext.Provider, {
  44. value: renderTimesRef.current
  45. }, /*#__PURE__*/React.createElement(Component, _extends({}, props, refProps)));
  46. };
  47. if (process.env.NODE_ENV !== 'production') {
  48. ImmutableComponent.displayName = "ImmutableRoot(".concat(Component.displayName || Component.name, ")");
  49. }
  50. return refAble ? /*#__PURE__*/React.forwardRef(ImmutableComponent) : ImmutableComponent;
  51. }
  52. /**
  53. * Wrapped Component with `React.memo`.
  54. * But will rerender when parent with `makeImmutable` rerender.
  55. */
  56. function responseImmutable(Component, propsAreEqual) {
  57. var refAble = supportRef(Component);
  58. var ImmutableComponent = function ImmutableComponent(props, ref) {
  59. var refProps = refAble ? {
  60. ref: ref
  61. } : {};
  62. useImmutableMark();
  63. return /*#__PURE__*/React.createElement(Component, _extends({}, props, refProps));
  64. };
  65. if (process.env.NODE_ENV !== 'production') {
  66. ImmutableComponent.displayName = "ImmutableResponse(".concat(Component.displayName || Component.name, ")");
  67. }
  68. return refAble ? /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef(ImmutableComponent), propsAreEqual) : /*#__PURE__*/React.memo(ImmutableComponent, propsAreEqual);
  69. }
  70. return {
  71. makeImmutable: makeImmutable,
  72. responseImmutable: responseImmutable,
  73. useImmutableMark: useImmutableMark
  74. };
  75. }