k98kurz icon

diff.js

k98kurz | PRO | 03/05/21 03:53:07 PM UTC (Edited) | 0 ⭐ | 667 👁️ | Never ⏰ | []
JavaScript |

4.09 KB

|

None

|

0 👍

/

0 👎

/* Helper functions that can be used in componentDidUpdate to find what changed between component updates.
  Example: componentDidUpdate(prevProps, prevState) {
    const propsChanged = changes(prevProps, this.props);
    const stateChanged = changes(prevState, this.state);
    const propsDiff = diff(prevProps, this.props);
    const stateDiff = diff(prevState, this.state);
 
    if (propsChanged.someDataThing) {
      this.doStuff(propsDiff.someDataThing);
    }
 
    if (stateChanged.intermediateValue) {
      this.continueThing();
    }
  }
*/
 
// Copyright (c) 2021 Jonathan Voss
// BSD0 license
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
// TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
// NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
// IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
// compares two objects and returns recursive boolean flags for what properties are different
// flags will not appear for any non-array without a difference in content
// flag will be false for two equivalent arrays that are different instances
export function changes (obj1, obj2) {
  let flags = {};
 
  Object.keys(obj2).forEach(k => {
    if ((!obj1[k] && !!obj2[k]) || obj1[k] !== obj2[k]) {
      if (typeof obj1[k] == 'undefined' || typeof obj2[k] == 'undefined' || obj1[k] == null || obj2[k] == null || obj1[k].constructor.name !== obj2[k].constructor.name) {
        flags[k] = true;
      } else {
        switch (obj1[k].constructor.name) {
          case 'Array':
            flags[k] = (obj2[k].constructor.name == 'Array') ? obj1[k].filter(x => !obj2[k].includes(x)).length > 0 : true;
            break;
          case 'Object':
            flags[k] = changes(obj1[k], obj2[k]);
            break;
          default:
            flags[k] = true;
        }
      }
    }
  });
 
  Object.keys(obj1).forEach(k => {
    if ((!!obj1[k] && !obj2[k]) || obj1[k] !== obj2[k]) {
      if (typeof obj1[k] == 'undefined' || typeof obj2[k] == 'undefined' || obj1[k] == null || obj2[k] == null || obj1[k].constructor.name !== obj2[k].constructor.name) {
        flags[k] = true;
      } else {
        switch (obj2[k].constructor.name) {
          case 'Array':
            flags[k] = (obj1[k].constructor.name == 'Array') ? obj2[k].filter(x => !obj1[k].includes(x)).length > 0 : true;
            break;
          case 'Object':
            flags[k] = changes(obj1[k], obj2[k]);
            if (flags[k].constructor.name == 'Object' && Object.keys(flags[k]).length < 1) {
              delete flags[k];
            }
            break;
          default:
            flags[k] = true;
        }
      }
    }
  });
 
  return flags;
}
 
// compares two objects and returns whatever properties were overwritten by obj2
export function diff (obj1, obj2) {
  let flags = changes(obj1, obj2);
  let difference = {};
  Object.keys(flags).forEach(k => {
    if (typeof obj1[k] == 'undefined' || typeof obj2[k] == 'undefined' || obj1[k] == null || obj2[k] == null || obj1[k].constructor.name !== obj2[k].constructor.name) {
      difference[k] = obj2[k];
      return;
    }
 
    switch (obj1[k].constructor.name) {
      case 'Array':
        if (obj2[k].constructor.name)
          difference[k] = obj2[k].filter(x => !obj1[k].includes(k));
        else
          difference[k] = obj2[k];
        break;
      case 'Object':
        difference[k] = diff(obj1[k], obj2[k]);
        if (Object.keys(difference[k]).length < 1) {
          delete difference[k];
        }
        break;
      case 'Number':
      case 'Boolean':
      case 'Boolean':
      case 'String':
      default:
        difference[k] = obj2[k];
    }
  });
 
  return difference;
}
 

Comments