tree-changes
Get changes between two versions of data with similar shape.
Setup
npm install tree-changes
Usage
import treeChanges from 'tree-changes';
const savedData = {
actions: {},
data: { a: 1 },
hasData: false,
items: [{ name: 'test' }],
messages: [],
missing: 'username',
pristine: true,
ratio: 0.9,
retries: 0,
sort: {
data: [{ type: 'asc' }, { type: 'desc' }],
status: 'idle',
},
switch: false,
username: '',
};
const newData = {
actions: { complete: true },
data: {},
hasData: true,
items: [],
messages: ['New Message'],
missing: '',
ratio: 0.5,
retries: 1,
sort: {
data: [{ type: 'desc' }, { type: 'asc' }],
status: 'success',
},
sudo: true,
username: 'John',
};
const {
added,
changed,
changedFrom,
decreased,
emptied,
filled,
increased,
removed,
} = treeChanges(savedData, newData);
changed();
changed('hasData');
changed('hasData', true);
changed('hasData', true, false);
changed('actions', { complete: true }, {})
changed('sort.data.0.type', 'desc');
changedFrom('hasData', false);
changedFrom('hasData', false, true);
changedFrom('retries', 0);
changedFrom('retries', 0, 1);
changedFrom('sort.status', 'idle', ['done', 'success']);
added('actions');
added('messages');
added('sudo');
removed();
removed('data');
removed('items');
removed('switch');
filled('actions');
filled('messages');
filled('username');
emptied('data');
emptied('items');
emptied('missing');
decreased('ratio');
increased('retries');
Works with arrays too.
import treeChanges from 'tree-changes';
const { changed } = treeChanges([0, { id: 2 }], [0, { id: 4 }]);
changed();
changed(0);
changed(1);
changed('1.id', 4);
It uses deep-diff to compare objects/arrays and nested-property to get the nested key.
API
added(key: Key
)
Check if something was added to the data (length has increased). Works with arrays and objects (using Object.keys).
changed(key?: Key
, actual?: Value
, previous?: Value
)
Check if the data has changed.
It also can compare to the actual
value or even with the previous
.
changedFrom(key: Key
, previous: Value
, actual?: Value
)
Check if the data has changed from previous
or from previous
to actual
.
decreased(key: Key
, actual?: Value
, previous?: Value
)
Check if both values are numbers and the value has decreased.
It also can compare to the actual
value or even with the previous
.
emptied(key: Key
)
Check if the data was emptied. Works with arrays, objects and strings.
filled(key: Key
)
Check if the data was filled (from a previous empty value). Works with arrays, objects and strings.
increased(key: Key
, actual?: Value
, previous?: Value
)
Check if both values are numbers and the value has increased.
It also can compare to the actual
value or even with the previous
.
removed(key: Key
)
Check if something was removed from the data (length has decreased). Works with arrays and objects (using Object.keys).
Types
type Key = string | number;
type AcceptedTypes = string | boolean | number | { [key: string]: any };
type Value = AcceptedTypes | AcceptedTypes[];
With React
Class components
import treeChanges from 'tree-changes';
class Comp extends React.Component {
...
componentDidUpdate(prevProps) {
const { changed, changedFrom } = treeChanges(prevProps, this.props);
if (changedFrom('retries', 0, 1) {
}
if (changed('hasData', true)) {
}
}
...
}
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 { changed } = useTreeChanges(props);
if (changed('isLoaded', true)) {
sendAnalyticsEvent('load', 'MySuperPage')
}
return <div>...</div>;
};
License
MIT