1
- import { memo , useCallback } from "react" ;
1
+ import { memo } from "react" ;
2
2
import { createRoot } from 'react-dom/client' ;
3
- import { createSignal , useSelector , useSignal } from "react-tagged-state" ;
3
+ import { createSignal , useSelector } from "react-tagged-state" ;
4
4
5
5
const A = [ "pretty" , "large" , "big" , "small" , "tall" , "short" , "long" , "handsome" , "plain" , "quaint" , "clean" ,
6
6
"elegant" , "easy" , "angry" , "crazy" , "helpful" , "mushy" , "odd" , "unsightly" , "adorable" , "important" , "inexpensive" ,
@@ -19,48 +19,94 @@ const buildData = (count) => {
19
19
for ( let index = 0 ; index < count ; index ++ ) {
20
20
res [ index ] = {
21
21
id : nextId ++ ,
22
- label : `${ A [ random ( A . length ) ] } ${ C [ random ( C . length ) ] } ${ N [ random ( N . length ) ] } `
22
+ labelSignal : createSignal ( `${ A [ random ( A . length ) ] } ${ C [ random ( C . length ) ] } ${ N [ random ( N . length ) ] } ` ) ,
23
+ isSelectedSignal : createSignal ( false )
23
24
} ;
24
25
}
25
26
26
27
return res ;
27
28
}
28
29
29
- const data = createSignal ( [ ] ) ;
30
+ const dataSignal = createSignal ( [ ] ) ;
30
31
31
- let selected = createSignal ( 0 ) ;
32
+ let selectedSignal = createSignal ( null ) ;
33
+
34
+ const select = ( item ) => {
35
+ selectedSignal ( ( prev ) => {
36
+ if ( prev ) {
37
+ prev . isSelectedSignal ( false ) ;
38
+ }
39
+
40
+ if ( item ) {
41
+ item . isSelectedSignal ( true ) ;
42
+ }
43
+
44
+ return item ;
45
+ } ) ;
46
+ } ;
47
+
48
+ const run = ( ) => {
49
+ dataSignal ( buildData ( 1000 ) ) ;
50
+ select ( null ) ;
51
+ } ;
52
+
53
+ const runLots = ( ) => {
54
+ dataSignal ( buildData ( 10000 ) ) ;
55
+ select ( null ) ;
56
+ } ;
57
+
58
+ const add = ( ) => {
59
+ dataSignal ( ( curr ) => curr . concat ( buildData ( 1000 ) ) ) ;
60
+ } ;
61
+
62
+ const update = ( ) => {
63
+ const items = dataSignal ( ) ;
64
+
65
+ for ( let index = 0 ; index < items . length ; index += 10 ) {
66
+ items [ index ] . labelSignal ( ( labelSignal ) => labelSignal + " !!!" ) ;
67
+ }
68
+ } ;
69
+
70
+ const clear = ( ) => {
71
+ dataSignal ( [ ] ) ;
72
+ select ( null ) ;
73
+ } ;
74
+
75
+ const swap = ( ) => {
76
+ dataSignal ( ( curr ) => [ curr [ 0 ] , curr [ 998 ] , ...curr . slice ( 2 , 998 ) , curr [ 1 ] , curr [ 999 ] ] ) ;
77
+ } ;
78
+
79
+ const remove = ( id ) => dataSignal ( ( curr ) => curr . filter ( ( item ) => item . id !== id ) ) ;
32
80
33
81
const GlyphIcon = (
34
82
< span className = "glyphicon glyphicon-remove" aria-hidden = "true" />
35
83
) ;
36
84
37
- const Row = memo ( ( { item} ) => {
38
- const isSelected = useSelector ( ( ) => item . id === selected ( ) , { pure : true } ) ;
39
- const handleSelect = useCallback ( ( ) => {
40
- selected ( item . id ) ;
41
- } , [ item . id ] ) ;
42
- const handleRemove = useCallback ( ( ) => {
43
- data ( ( curr ) => curr . filter ( ( { id} ) => id !== item . id ) ) ;
44
- } , [ item . id ] ) ;
45
-
46
- return (
47
- < tr className = { isSelected ? "danger" : "" } >
48
- < td className = "col-md-1" > { item . id } </ td >
49
- < td className = "col-md-4" >
50
- < a onClick = { handleSelect } > { item . label } </ a >
51
- </ td >
52
- < td className = "col-md-1" >
53
- < a onClick = { handleRemove } > { GlyphIcon } </ a >
54
- </ td >
55
- < td className = "col-md-6" />
56
- </ tr >
57
- )
58
- } ) ;
59
-
60
- const RowList = ( ) => {
61
- const items = useSignal ( data ) ;
62
-
63
- return items . map ( ( item ) => < Row key = { item . id } item = { item } /> )
85
+ const SelectableRow = ( { isSelectedSignal, children} ) => (
86
+ < tr className = { useSelector ( isSelectedSignal ) ? "danger" : "" } >
87
+ { children }
88
+ </ tr >
89
+ ) ;
90
+
91
+ const Label = ( { labelSignal} ) => useSelector ( labelSignal ) ;
92
+
93
+ const ListItem = memo ( ( { item} ) => (
94
+ < SelectableRow isSelectedSignal = { item . isSelectedSignal } >
95
+ < td className = "col-md-1" > { item . id } </ td >
96
+ < td className = "col-md-4" >
97
+ < a onClick = { ( ) => select ( item ) } > < Label labelSignal = { item . labelSignal } /> </ a >
98
+ </ td >
99
+ < td className = "col-md-1" >
100
+ < a onClick = { ( ) => remove ( item . id ) } > { GlyphIcon } </ a >
101
+ </ td >
102
+ < td className = "col-md-6" />
103
+ </ SelectableRow >
104
+ ) ) ;
105
+
106
+ const List = ( ) => {
107
+ const items = useSelector ( dataSignal ) ;
108
+
109
+ return items . map ( ( item ) => < ListItem key = { item . id } item = { item } /> )
64
110
} ;
65
111
66
112
const Button = ( { id, title, cb} ) => (
@@ -76,44 +122,19 @@ const Main = () => (
76
122
< div className = "col-md-6" > < h1 > React Tagged State </ h1 > </ div >
77
123
< div className = "col-md-6" >
78
124
< div className = "row" >
79
- < Button id = "run" title = "Create 1,000 rows" cb = { ( ) => {
80
- data ( buildData ( 1000 ) ) ;
81
- selected ( 0 ) ;
82
- } } />
83
- < Button id = "runlots" title = "Create 10,000 rows" cb = { ( ) => {
84
- data ( buildData ( 10000 ) ) ;
85
- selected ( 0 ) ;
86
- } } />
87
- < Button id = "add" title = "Append 1,000 rows" cb = { ( ) => {
88
- data ( ( curr ) => curr . concat ( buildData ( 1000 ) ) ) ;
89
- } } />
90
- < Button id = "update" title = "Update every 10th row" cb = { ( ) => {
91
- data ( ( curr ) => {
92
- const copy = curr . slice ( 0 ) ;
93
-
94
- for ( let index = 0 ; index < copy . length ; index += 10 ) {
95
- const item = copy [ index ] ;
96
-
97
- copy [ index ] = { id : item . id , label : item . label + " !!!" } ;
98
- }
99
-
100
- return copy ;
101
- } ) ;
102
- } } />
103
- < Button id = "clear" title = "Clear" cb = { ( ) => {
104
- data ( [ ] ) ;
105
- selected ( 0 ) ;
106
- } } />
107
- < Button id = "swaprows" title = "Swap Rows" cb = { ( ) => {
108
- data ( ( curr ) => [ curr [ 0 ] , curr [ 998 ] , ...curr . slice ( 2 , 998 ) , curr [ 1 ] , curr [ 999 ] ] ) ;
109
- } } />
125
+ < Button id = "run" title = "Create 1,000 rows" cb = { run } />
126
+ < Button id = "runlots" title = "Create 10,000 rows" cb = { runLots } />
127
+ < Button id = "add" title = "Append 1,000 rows" cb = { add } />
128
+ < Button id = "update" title = "Update every 10th row" cb = { update } />
129
+ < Button id = "clear" title = "Clear" cb = { clear } />
130
+ < Button id = "swaprows" title = "Swap Rows" cb = { swap } />
110
131
</ div >
111
132
</ div >
112
133
</ div >
113
134
</ div >
114
135
< table className = "table table-hover table-striped test-data" >
115
136
< tbody >
116
- < RowList />
137
+ < List />
117
138
</ tbody >
118
139
</ table >
119
140
< span className = "preloadicon glyphicon glyphicon-remove" aria-hidden = "true" />
0 commit comments