@@ -2,31 +2,50 @@ import React from "react";
2
2
import jsonpatch from "fast-json-patch" ;
3
3
4
4
export function useJsonPatchCallback ( initial ) {
5
- const model = React . useRef ( initial ) ;
5
+ const doc = React . useRef ( initial ) ;
6
6
const forceUpdate = useForceUpdate ( ) ;
7
7
8
8
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
+ ] ) ;
14
34
}
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 ;
24
35
forceUpdate ( ) ;
25
36
} ,
26
- [ model ]
37
+ [ doc ]
27
38
) ;
28
39
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 ;
30
49
}
31
50
32
51
function useForceUpdate ( ) {
0 commit comments