You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

functions.js 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /* @flow */
  2. import _ from 'lodash';
  3. /**
  4. * Sets specific properties of a specific state to specific values and prevents
  5. * unnecessary state changes.
  6. *
  7. * @param {Object} target - The state on which the specified properties are to
  8. * be set.
  9. * @param {Object} source - The map of properties to values which are to be set
  10. * on the specified target.
  11. * @returns {Object} The specified target if the values of the specified
  12. * properties equal the specified values; otherwise, a new state constructed
  13. * from the specified target by setting the specified properties to the
  14. * specified values.
  15. */
  16. export function assign(target: Object, source: Object) {
  17. let t = target;
  18. for (const property in source) { // eslint-disable-line guard-for-in
  19. t = set(t, property, source[property], t === target);
  20. }
  21. return t;
  22. }
  23. /**
  24. * Determines whether {@code a} equals {@code b} according to deep comparison
  25. * (which makes sense for Redux and its state definition).
  26. *
  27. * @param {*} a - The value to compare to {@code b}.
  28. * @param {*} b - The value to compare to {@code a}.
  29. * @returns {boolean} True if {@code a} equals {@code b} (according to deep
  30. * comparison); false, otherwise.
  31. */
  32. export function equals(a: any, b: any) {
  33. return _.isEqual(a, b);
  34. }
  35. /**
  36. * Sets a specific property of a specific state to a specific value. Prevents
  37. * unnecessary state changes (when the specified <tt>value</tt> is equal to the
  38. * value of the specified <tt>property</tt> of the specified <tt>state</tt>).
  39. *
  40. * @param {Object} state - The (Redux) state from which a new state is to be
  41. * constructed by setting the specified <tt>property</tt> to the specified
  42. * <tt>value</tt>.
  43. * @param {string} property - The property of <tt>state</tt> which is to be
  44. * assigned the specified <tt>value</tt> (in the new state).
  45. * @param {*} value - The value to assign to the specified <tt>property</tt>.
  46. * @returns {Object} The specified <tt>state</tt> if the value of the specified
  47. * <tt>property</tt> equals the specified <tt>value/tt>; otherwise, a new state
  48. * constructed from the specified <tt>state</tt> by setting the specified
  49. * <tt>property</tt> to the specified <tt>value</tt>.
  50. */
  51. export function set(state: Object, property: string, value: any) {
  52. return _set(state, property, value, /* copyOnWrite */ true);
  53. }
  54. /* eslint-disable max-params */
  55. /**
  56. * Sets a specific property of a specific state to a specific value. Prevents
  57. * unnecessary state changes (when the specified <tt>value</tt> is equal to the
  58. * value of the specified <tt>property</tt> of the specified <tt>state</tt>).
  59. *
  60. * @param {Object} state - The (Redux) state from which a state is to be
  61. * constructed by setting the specified <tt>property</tt> to the specified
  62. * <tt>value</tt>.
  63. * @param {string} property - The property of <tt>state</tt> which is to be
  64. * assigned the specified <tt>value</tt>.
  65. * @param {*} value - The value to assign to the specified <tt>property</tt>.
  66. * @param {boolean} copyOnWrite - If the specified <tt>state</tt> is to not be
  67. * modified, <tt>true</tt>; otherwise, <tt>false</tt>.
  68. * @returns {Object} The specified <tt>state</tt> if the value of the specified
  69. * <tt>property</tt> equals the specified <tt>value/tt> or <tt>copyOnWrite</tt>
  70. * is truthy; otherwise, a new state constructed from the specified
  71. * <tt>state</tt> by setting the specified <tt>property</tt> to the specified
  72. * <tt>value</tt>.
  73. */
  74. function _set(
  75. state: Object,
  76. property: string,
  77. value: any,
  78. copyOnWrite: boolean) {
  79. // Delete state properties that are to be set to undefined. (It is a matter
  80. // of personal preference, mostly.)
  81. if (typeof value === 'undefined'
  82. && Object.prototype.hasOwnProperty.call(state, property)) {
  83. const newState = copyOnWrite ? { ...state } : state;
  84. if (delete newState[property]) {
  85. return newState;
  86. }
  87. }
  88. if (state[property] !== value) {
  89. if (copyOnWrite) {
  90. return {
  91. ...state,
  92. [property]: value
  93. };
  94. }
  95. state[property] = value;
  96. }
  97. return state;
  98. }
  99. /* eslint-enable max-params */
  100. /**
  101. * If the specified <tt>stateOrGetState</tt> is a function, it is presumed to be
  102. * the redux {@link getState} function, it is invoked, and its return value is
  103. * returned; otherwise, <tt>stateOrGetState</tt> is presumed to be the redux
  104. * state and is returned.
  105. *
  106. * @param {Object|Function} stateOrGetState - The redux state or
  107. * {@link getState} function.
  108. * @returns {Object} The redux state.
  109. */
  110. export function toState(stateOrGetState: Object | Function) {
  111. return (
  112. typeof stateOrGetState === 'function'
  113. ? stateOrGetState()
  114. : stateOrGetState);
  115. }