@@ -2,31 +2,50 @@ import React from "react";
22import jsonpatch from "fast-json-patch" ;
33
44export function useJsonPatchCallback ( initial ) {
5- const model = React . useRef ( initial ) ;
5+ const doc = React . useRef ( initial ) ;
66 const forceUpdate = useForceUpdate ( ) ;
77
88 const applyPatch = React . useCallback (
9- ( pathPrefix , patch ) => {
10- if ( pathPrefix ) {
11- patch = patch . map ( ( op ) =>
12- Object . assign ( { } , op , { path : pathPrefix + op . path } )
13- ) ;
9+ ( path , patch ) => {
10+ if ( ! path ) {
11+ // We CANNOT mutate the part of the document because React checks some
12+ // attributes of the model (e.g. model.attributes.style is checked for
13+ // identity).
14+ doc . current = applyNonMutativePatch ( doc , patch , false , false , true ) ;
15+ } else {
16+ // We CAN mutate the document here though because we know that nothing above
17+ // The patch `path` is changing. Thus, maintaining the identity for that section
18+ // of the model is accurate.
19+ applyMutativePatch ( doc . current , [
20+ {
21+ op : "replace" ,
22+ path : path ,
23+ // We CANNOT mutate the part of the document where the actual patch is being
24+ // applied. Instead we create a copy because React checks some attributes of
25+ // the model (e.g. model.attributes.style is checked for identity). The part
26+ // of the document above the `path` can be mutated though because we know it
27+ // has not changed.
28+ value : applyNonMutativePatch (
29+ jsonpatch . getValueByPointer ( doc . current , path ) ,
30+ patch
31+ ) ,
32+ } ,
33+ ] ) ;
1434 }
15- // Always return a newDocument because React checks some attributes of the model
16- // (e.g. model.attributes.style is checked for identity)
17- model . current = jsonpatch . applyPatch (
18- model . current ,
19- patch ,
20- false ,
21- false ,
22- true
23- ) . newDocument ;
2435 forceUpdate ( ) ;
2536 } ,
26- [ model ]
37+ [ doc ]
2738 ) ;
2839
29- return [ model . current , applyPatch ] ;
40+ return [ doc . current , applyPatch ] ;
41+ }
42+
43+ function applyNonMutativePatch ( doc , patch ) {
44+ return jsonpatch . applyPatch ( doc , patch , false , false , true ) . newDocument ;
45+ }
46+
47+ function applyMutativePatch ( doc , patch ) {
48+ jsonpatch . applyPatch ( doc , patch , false , true , true ) . newDocument ;
3049}
3150
3251function useForceUpdate ( ) {
0 commit comments