Skip to content
Get changes between two versions of the same object
TypeScript JavaScript
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src
test
.codeclimate.yml
.editorconfig
.gitignore
.travis.yml
LICENSE
README.md
jest.config.js
package-lock.json
package.json
tsconfig.json
tslint.json

README.md

tree-changes

NPM version build status Maintainability Test Coverage

Get changes between two versions of data with similar shape.

Setup

npm install tree-changes

Usage

import treeChanges from 'tree-changes';

const savedData = {
    data: { a: 1 },
    hasData: false,
    items: [{ name: 'test' }],
    ratio: 0.9,
    retries: 0,
  	sort: {
      data: [{ type: 'asc' }, { type: 'desc' }],
      status: 'idle',
    },
    switch: false,
};

const newData = {
    data: { a: 1 },
    hasData: true,
    items: [],
    ratio: 0.5,
    retries: 1,
  	sort: {
      data: [{ type: 'desc' }, { type: 'asc' }],
      status: 'success',
    },
};

const {
  changed,
  changedFrom,
  changedTo,
  increased,
  decreased,
} = treeChanges(savedData, newData);

if (changed('hasData')) {
    // execute some side-effect
}

if (changedFrom('retries', 0, 1) {
    // should we try again?
}

// works with array values too
if (changedFrom('sort.status', 'idle', ['done', 'success']) {
    // status has changed!
}

// support nested match 
if (changedTo('sort.data.0.type', 'desc') {
    // update the type
}

if (decreased('ratio')) {
    // do something!
}

if (increased('retries')) {
    // hey, slow down.
}

Works with arrays too.

import treeChanges from 'tree-changes';

const { changed, changedTo } = treeChanges([0, { id: 2 }], [0, { id: 4 }]);

changed(); // true
changed(0); // false
changed(1); // true
changedTo('1.id', 4); // true

It uses deep-diff to compare plain objects/arrays and nested-property to get the nested key.

With React

Class components

import treeChanges from 'tree-changes';

class Comp extends React.Component {
    ...
    componentDidUpdate(prevProps) {
        const { changedFrom, changedTo } = treeChanges(prevProps, this.props);
        
        if (changedFrom('retries', 0, 1) {
            // dispatch some error
        }
        
        if (changedTo('hasData', true)) {
            // send data to analytics or something.
        }
    }
    ...
}

Functional components with hooks

import React, { useEffect, useRef } from 'react';
import treeChanges from 'tree-changes';

function usePrevious(value) {
  const ref = useRef();

  useEffect(() => {
    ref.current = value;
  });

  return ref.current;
}

function useTreeChanges(props) {
  const prevProps = usePrevious(props) || {};

  return treeChanges(prevProps, props);
}

const Page = (props) => {
  const { changedTo } = useTreeChanges(props);

  if (changedTo('isLoaded', true)) {
    sendAnalyticsEvent('load', 'MySuperPage')
  }

  return <div>...</div>;
};

API

changed(key: KeyType)
Check if the value has changed. Supports objects and arrays.

changedFrom(key: KeyType, previous: InputType, actual?: InputType)
Check if the value has changed from previous to actual.

changedTo(key: KeyType, actual: InputType)
Check if the value has changed to actual.

increased(key: KeyType)
Check if both versions are numbers and the value has increased.

decreased(key: KeyType)
Check if both versions are numbers and the value has decreased.

type KeyType = string | number; type InputType = string | boolean | number | object | Array<string | boolean | number | object>;

You can’t perform that action at this time.