Gathering detailed insights and metrics for redux-deep-diff
Gathering detailed insights and metrics for redux-deep-diff
Gathering detailed insights and metrics for redux-deep-diff
Gathering detailed insights and metrics for redux-deep-diff
deep-object-diff
Deep diffs two objects, including nested structures of arrays and objects, and return the difference.
arr-diff
Returns an array with only the unique values from the first array, by excluding all values from additional arrays using strict equality for comparisons.
diff-match-patch
npm package for https://github.com/google/diff-match-patch
deep-diff
Javascript utility for calculating deep difference, capturing changes, and applying changes across objects; for nodejs and the browser.
npm install redux-deep-diff
Module System
Min. Node Version
Typescript Support
Node Version
NPM Version
23 Stars
52 Commits
4 Forks
3 Watching
10 Branches
3 Contributors
Updated on 14 Oct 2024
JavaScript (100%)
Cumulative downloads
Total Downloads
Last day
500%
12
Compared to previous day
Last week
205.6%
55
Compared to previous week
Last month
6.3%
134
Compared to previous month
Last year
-44%
2,015
Compared to previous year
2
22
deep-diff for tracking structural differences between objects in redux state containers
Also with undo/redo functionality!
1$ yarn add redux-deep-diff
redux-deep-diff
is a reducer enhancer (higher-order reducer), it provides the
diff function, which takes an existing reducer and a configuration object and
enhances your existing reducer with deep-diff functionality.
Note: the deep-diff
library calculates structural changes between two
javascript objects. As such, your state must be a diffable object.
To use redux-deep-diff
, first import it, then add the diff enhancer to your
reducer(s) like so:
1import { combineReducers } from 'redux'; 2 3// redux-deep-diff higher-order reducer 4import diff from 'redux-deep-diff'; 5 6// `counter` state must be a diffable object 7// e.i. state.counter = { count: 1 } 8export default combineReducers({ 9 counter: diff(counter, /* [config] */) 10})
To configure how diff
enchances your reducers, see the
possible configuration options below.
Wrapping your reducer with diff
adds a diff leaf to your state:
1{ 2 diff: { 3 prev: [...previousDiffs], 4 next: [...futureDiffs] 5 } 6}
Each diff in the history is an array of changes. See deep-diff's differences documentation for more info on change records.
undo
& redo
actionsSince redux-deep-diff
tracks changes to your state, you can undo & redo
the diffs in your history.
1import { undo, redo, jump } from 'redux-deep-diff'; 2 3store.dispatch(undo()); // revert the previous diff 4store.dispatch(redo()); // apply the next diff 5 6store.dispatch(jump(-3)); // revert the previous three diffs 7store.dispatch(jump(2)); // apply the next two diffs
clear
action1import { clear } from 'redux-deep-diff'; 2 3store.dispatch(clear()); // clear the history
To access previous values of the state, redux-deep-diff
has a concept of
deducers
which are similar to selectors in that you create a deducer
and use
it to calculate ("deduce") part of your state's history.
1import { createDeducer } from 'redux-deep-diff'; 2 3const countSelector = (counter) => counter.count; 4const getCountHistory = createDeducer(countSelector, /* [config] */); 5 6// `state.counter` must countain a diff history leaf 7getCountHistory(state.counter); //=> [0, 1, 2, 3, 2, ...]
To configure how a deducer
determines which diffs to deduce, see the
possible configuration options below.
Similarly to selectors, deducers
are also memoized and not only memoize their
return value, but the return value of the selector for each set of changes in
the diff history. When the diff history changes, deducers
will only call the
selector with states it hasn't yet deduced.
1store.dispatch(increment()); 2let a = getCountHistory(store.getState()); 3//=> [0, 1] `countSelector` was called twice 4 5store.dispatch(increment()); 6store.dispatch(increment()); 7store.dispatch(decrement()); 8 9let b = getCountHistory(store.getState()); 10//=> [0, 1, 2, 3, 2] `countSelector` was called three more times 11 12// true even for values of objects/arrays 13expect(a[0]).to.equal(b[0]); 14expect(a[1]).to.equal(b[1]); 15 16let c = getCountHistory(store.getState()); 17//=> [0, 1, 2, 3, 2] `countSelector` was not called 18 19// when no changes are made, the same results are returned 20expect(b).to.equal(c); 21// ...but a new array is returned when values do change 22expect(a).to.not.equal(b);
Default values for the supported options are listed below
1{ 2 key: 'diff', // key to store the state diffs 3 limit: 0, // diff history limit 4 undoType: '@@redux-deep-diff/UNDO', // custom undo action type 5 redoType: '@@redux-deep-diff/REDO', // custom redo action type 6 jumpType: '@@redux-deep-diff/JUMP', // custom jump action type 7 clearType: '@@redux-deep-diff/CLEAR', // custom clear action type 8 skipAction: (action) => false, // return true to skip diffing the state for this action 9 initialState: { prev: [], next: [] }, // initial diff history state 10 ignoreInit: true, // includes the first state when `false` 11 prefilter: (path, key) => false, // (see below) 12 flatten: (path, key) => false // (see below) 13}
See deep-diff
's prefilter argument.
Similar to prefilter
, flatten
should return a truthy value for any path-key
combination that should be flattened. That is: deep-diff
will not do any
further analysis on the object-property path, but the resulting value of the
change will be the value located at the flattened path.
1let flatten = (path, key) => key === 'nested'; 2 3/* ...reducer setup... */ 4 5expect(state.nested).to.deep.equal({ some: 'property' }) 6expect(change.path).to.deep.equal(['nested']); 7expect(change.lhs).to.deep.equal({ some: 'prev-property' }); 8expect(change.rhs).to.deep.equal({ some: 'property' });
1{ 2 key: 'diff', // key to retrieve the state diffs 3 next: false, // deduce from `diff.next` when `true` (future history) 4 unique: false, // skip equal results that immediately follow each other 5 index: false, // the index of a single state in the history to deduce 6 range: false, // a range of history states to deduce - `[lower, upper]` 7 limit: false // limit the deducer to a specified length 8}
Important: index
, range
, and limit
may not be used in conjuction. If
they are used together, precedence will be taken in that order and a warning
will be logged.
MIT, see LICENSE.md
for more info.
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
Found 2/24 approved changesets -- score normalized to 0
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
37 existing vulnerabilities detected
Details
Score
Last Scanned on 2024-11-18
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More