@@ -22,29 +22,19 @@ function identityFn(n) {
22
22
}
23
23
24
24
export default function createCopyOnWriteState ( baseState ) {
25
- /**
26
- * The current state is stored in a closure, shared by the consumers and
27
- * the provider. Consumers still respect the Provider/Consumer contract
28
- * that React context enforces, by only accessing state in the consumer.
29
- */
30
- let currentState = baseState ;
31
- let providerListener = null ;
25
+ let updateState = null ;
32
26
const State = React . createContext ( baseState ) ;
33
27
// Wraps immer's produce. Only notifies the Provider
34
28
// if the returned draft has been changed.
35
29
function mutate ( fn ) {
36
30
invariant (
37
- providerListener !== null ,
31
+ updateState !== null ,
38
32
`mutate(...): you cannot call mutate when no CopyOnWriteStoreProvider ` +
39
33
`instance is mounted. Make sure to wrap your consumer components with ` +
40
34
`the returned Provider, and/or delay your mutate calls until the component ` +
41
35
`tree is moutned.`
42
36
) ;
43
- const nextState = produce ( currentState , draft => fn ( draft , currentState ) ) ;
44
- if ( nextState !== currentState ) {
45
- currentState = nextState ;
46
- providerListener ( ) ;
47
- }
37
+ updateState ( fn ) ;
48
38
}
49
39
50
40
/**
@@ -60,28 +50,29 @@ export default function createCopyOnWriteState(baseState) {
60
50
}
61
51
62
52
class CopyOnWriteStoreProvider extends React . Component {
63
- state = this . props . initialState || currentState ;
53
+ state = this . props . initialState || baseState ;
64
54
65
55
componentDidMount ( ) {
66
56
invariant (
67
- providerListener === null ,
57
+ updateState === null ,
68
58
`CopyOnWriteStoreProvider(...): There can only be a single ` +
69
59
`instance of a provider rendered at any given time.`
70
60
) ;
71
- providerListener = this . updateState ;
72
- // Allow a Provider to initialize state from props
73
- if ( this . props . initialState ) {
74
- currentState = this . props . initialState ;
75
- }
61
+ updateState = this . updateState ;
76
62
}
77
63
78
64
componentWillUnmount ( ) {
79
- providerListener = null ;
80
- currentState = baseState ;
65
+ updateState = null ;
81
66
}
82
67
83
- updateState = ( ) => {
84
- this . setState ( currentState ) ;
68
+ updateState = fn => {
69
+ this . setState ( state => {
70
+ const nextState = produce ( state , draft => fn ( draft , state ) ) ;
71
+ if ( nextState === state ) {
72
+ return null ;
73
+ }
74
+ return nextState ;
75
+ } ) ;
85
76
} ;
86
77
87
78
render ( ) {
0 commit comments