1
1
import randomWords from "random-words" ;
2
2
import { v4 as uuid } from "uuid" ;
3
- import React , { useEffect , useMemo } from "react" ;
3
+ import * as React from "react" ;
4
4
import { connectToDB , getConnection } from "./sharedb" ;
5
5
import {
6
6
Link ,
9
9
useLocation ,
10
10
} from "react-router-dom" ;
11
11
12
+ const useTransition : ( ) => [ ( fn : Function ) => void , boolean ] = ( React as any )
13
+ . unstable_useTransition ;
14
+
12
15
interface Node {
13
16
text : string ;
14
17
}
@@ -26,16 +29,21 @@ function useFlow(config: {
26
29
addNode : ( ) => void ;
27
30
removeNode : ( id : string ) => void ;
28
31
reset : ( flow : Flow ) => void ;
32
+ isPending : boolean ;
29
33
} {
30
34
// Setup
31
35
36
+ const [ startTransition , isPending ] = useTransition ( ) ;
37
+
32
38
const [ state , setState ] = React . useState < Flow | null > ( null ) ;
33
39
34
- const doc = useMemo ( ( ) => getConnection ( config . id ) , [ config . id ] ) ;
40
+ const doc = React . useMemo ( ( ) => getConnection ( config . id ) , [ config . id ] ) ;
35
41
36
- useEffect ( ( ) => {
42
+ React . useEffect ( ( ) => {
37
43
const cloneStateFromShareDB = ( ) =>
38
- setState ( JSON . parse ( JSON . stringify ( doc . data ) ) ) ;
44
+ startTransition ( ( ) => {
45
+ setState ( JSON . parse ( JSON . stringify ( doc . data ) ) ) ;
46
+ } ) ;
39
47
40
48
connectToDB ( doc ) . then ( ( ) => {
41
49
cloneStateFromShareDB ( ) ;
@@ -46,7 +54,7 @@ function useFlow(config: {
46
54
setState ( null ) ;
47
55
doc . destroy ( ) ;
48
56
} ;
49
- } , [ doc ] ) ;
57
+ } , [ doc , startTransition ] ) ;
50
58
51
59
// Methods
52
60
@@ -75,6 +83,7 @@ function useFlow(config: {
75
83
addNode,
76
84
removeNode,
77
85
reset,
86
+ isPending,
78
87
} ;
79
88
}
80
89
@@ -86,44 +95,47 @@ const Flow: React.FC<{ id: string }> = ({ id }) => {
86
95
}
87
96
88
97
return (
89
- < main >
90
- < button
91
- onClick = { ( ) => {
92
- flow . addNode ( ) ;
93
- } }
94
- >
95
- Add
96
- </ button >
97
- < button
98
- onClick = { ( ) => {
99
- fetch ( "/flow.json" )
100
- . then ( ( res ) => res . json ( ) )
101
- . then ( ( flowData ) => {
102
- flow . reset ( flowData ) ;
98
+ < >
99
+ < main >
100
+ < button
101
+ onClick = { ( ) => {
102
+ flow . addNode ( ) ;
103
+ } }
104
+ >
105
+ Add
106
+ </ button >
107
+ < button
108
+ onClick = { ( ) => {
109
+ fetch ( "/flow.json" )
110
+ . then ( ( res ) => res . json ( ) )
111
+ . then ( ( flowData ) => {
112
+ flow . reset ( flowData ) ;
113
+ } ) ;
114
+ } }
115
+ >
116
+ Import flow
117
+ </ button >
118
+ < button
119
+ onClick = { ( ) => {
120
+ flow . reset ( {
121
+ nodes : { } ,
122
+ edges : [ ] ,
103
123
} ) ;
104
- } }
105
- >
106
- Import flow
107
- </ button >
108
- < button
109
- onClick = { ( ) => {
110
- flow . reset ( {
111
- nodes : { } ,
112
- edges : [ ] ,
113
- } ) ;
114
- } }
115
- >
116
- Reset
117
- </ button >
118
- { Object . keys ( flow . state . nodes ) . map ( ( k ) => (
119
- < NodeView
120
- key = { k }
121
- onRemove = { flow . removeNode }
122
- id = { k }
123
- node = { flow . state . nodes [ k ] }
124
- />
125
- ) ) }
126
- </ main >
124
+ } }
125
+ >
126
+ Reset
127
+ </ button >
128
+ { Object . keys ( flow . state . nodes ) . map ( ( k ) => (
129
+ < NodeView
130
+ key = { k }
131
+ onRemove = { flow . removeNode }
132
+ id = { k }
133
+ node = { flow . state . nodes [ k ] }
134
+ />
135
+ ) ) }
136
+ </ main >
137
+ { flow . isPending && < div className = "overlay" /> }
138
+ </ >
127
139
) ;
128
140
} ;
129
141
@@ -176,7 +188,7 @@ const App = () => {
176
188
} , [ location ] ) ;
177
189
178
190
// If there is no ID readable from the hash, redirect to a freshly created one
179
- useEffect ( ( ) => {
191
+ React . useEffect ( ( ) => {
180
192
if ( id === null ) {
181
193
history . push ( `#${ randomWords ( ) } ` ) ;
182
194
}
0 commit comments