@@ -27,9 +27,79 @@ export type FixedSizeTreeState<T> = TreeState<
2727 FixedSizeNodeComponentProps < T > ,
2828 FixedSizeNodeRecord < T > ,
2929 FixedSizeNodeData < T > ,
30+ FixedSizeUpdateOptions ,
3031 T
3132> ;
3233
34+ const computeTree = < T extends { } > (
35+ {
36+ refreshNodes = false ,
37+ useDefaultOpenness = false ,
38+ } : FixedSizeUpdateOptions = { } ,
39+ { treeWalker} : FixedSizeTreeProps < T > ,
40+ { records : prevRecords , recomputeTree} : FixedSizeTreeState < T > ,
41+ ) : Pick < FixedSizeTreeState < T > , 'order' | 'records' > => {
42+ const order : Array < string | symbol > = [ ] ;
43+ const records = { ...prevRecords } ;
44+ const iter = treeWalker ( refreshNodes ) ;
45+
46+ if ( useDefaultOpenness ) {
47+ for ( const id in records ) {
48+ records [ id ] . isOpen = records [ id ] . data . isOpenByDefault ;
49+ }
50+ }
51+
52+ let isPreviousOpened = false ;
53+
54+ while ( true ) {
55+ const { done, value} = iter . next ( isPreviousOpened ) ;
56+
57+ if ( done || ! value ) {
58+ break ;
59+ }
60+
61+ let id : string | symbol ;
62+
63+ if ( typeof value === 'string' || typeof value === 'symbol' ) {
64+ id = value ;
65+
66+ if ( useDefaultOpenness ) {
67+ records [ id as string ] . isOpen =
68+ records [ id as string ] . data . isOpenByDefault ;
69+ }
70+ } else {
71+ ( { id} = value ) ;
72+ const { isOpenByDefault} = value ;
73+ const record = records [ id as string ] ;
74+
75+ if ( ! record ) {
76+ records [ id as string ] = {
77+ data : value ,
78+ isOpen : isOpenByDefault ,
79+ async toggle ( this : FixedSizeNodeRecord < T > ) : Promise < void > {
80+ this . isOpen = ! this . isOpen ;
81+ await recomputeTree ( { refreshNodes : this . isOpen } ) ;
82+ } ,
83+ } ;
84+ } else {
85+ record . data = value ;
86+
87+ if ( useDefaultOpenness ) {
88+ record . isOpen = isOpenByDefault ;
89+ }
90+ }
91+ }
92+
93+ order . push ( id ) ;
94+ isPreviousOpened = records [ id as string ] . isOpen ;
95+ }
96+
97+ return {
98+ order,
99+ records,
100+ } ;
101+ } ;
102+
33103export default class FixedSizeTree < T > extends React . PureComponent <
34104 FixedSizeTreeProps < T > ,
35105 FixedSizeTreeState < T >
@@ -38,13 +108,16 @@ export default class FixedSizeTree<T> extends React.PureComponent<
38108 rowComponent : Row ,
39109 } ;
40110
41- public static getDerivedStateFromProps ( {
42- children : component ,
43- itemData : treeData ,
44- } : FixedSizeTreeProps < { } > ) : Partial < FixedSizeTreeState < { } > > {
111+ public static getDerivedStateFromProps (
112+ props : FixedSizeTreeProps < { } > ,
113+ state : FixedSizeTreeState < { } > ,
114+ ) : Partial < FixedSizeTreeState < { } > > {
115+ const { children : component , itemData : treeData } = props ;
116+
45117 return {
46118 component,
47119 treeData,
120+ ...computeTree ( { refreshNodes : true } , props , state ) ,
48121 } ;
49122 }
50123
@@ -53,24 +126,23 @@ export default class FixedSizeTree<T> extends React.PureComponent<
53126 public constructor ( props : FixedSizeTreeProps < T > , context : any ) {
54127 super ( props , context ) ;
55128
56- this . createNodeRecord = this . createNodeRecord . bind ( this ) ;
57-
58129 const initialState : FixedSizeTreeState < T > = {
59130 component : props . children ,
60131 order : [ ] ,
132+ recomputeTree : this . recomputeTree . bind ( this ) ,
61133 records : { } ,
62134 } ;
63135
64136 this . state = {
65137 ...initialState ,
66- ...this . computeTree ( { refreshNodes : true } , props , initialState ) ,
138+ ...computeTree ( { refreshNodes : true } , props , initialState ) ,
67139 } ;
68140 }
69141
70142 public async recomputeTree ( options ?: FixedSizeUpdateOptions ) : Promise < void > {
71143 return new Promise ( resolve => {
72144 this . setState < never > (
73- prevState => this . computeTree ( options , this . props , prevState ) ,
145+ prevState => computeTree ( options , this . props , prevState ) ,
74146 resolve ,
75147 ) ;
76148 } ) ;
@@ -98,79 +170,4 @@ export default class FixedSizeTree<T> extends React.PureComponent<
98170 </ FixedSizeList >
99171 ) ;
100172 }
101-
102- private computeTree (
103- {
104- refreshNodes = false ,
105- useDefaultOpenness = false ,
106- } : FixedSizeUpdateOptions = { } ,
107- { treeWalker} : FixedSizeTreeProps < T > ,
108- { records : prevRecords } : FixedSizeTreeState < T > ,
109- ) : Pick < FixedSizeTreeState < T > , 'order' | 'records' > {
110- const order : Array < string | symbol > = [ ] ;
111- const records = { ...prevRecords } ;
112- const iter = treeWalker ( refreshNodes ) ;
113-
114- if ( useDefaultOpenness ) {
115- for ( const id in records ) {
116- records [ id ] . isOpen = records [ id ] . data . isOpenByDefault ;
117- }
118- }
119-
120- let isPreviousOpened = false ;
121-
122- while ( true ) {
123- const { done, value} = iter . next ( isPreviousOpened ) ;
124-
125- if ( done || ! value ) {
126- break ;
127- }
128-
129- let id : string | symbol ;
130-
131- if ( typeof value === 'string' || typeof value === 'symbol' ) {
132- id = value ;
133-
134- if ( useDefaultOpenness ) {
135- records [ id as string ] . isOpen =
136- records [ id as string ] . data . isOpenByDefault ;
137- }
138- } else {
139- ( { id} = value ) ;
140- const { isOpenByDefault} = value ;
141- const record = records [ id as string ] ;
142-
143- if ( ! record ) {
144- records [ id as string ] = this . createNodeRecord ( value ) ;
145- } else {
146- record . data = value ;
147-
148- if ( useDefaultOpenness ) {
149- record . isOpen = isOpenByDefault ;
150- }
151- }
152- }
153-
154- order . push ( id ) ;
155- isPreviousOpened = records [ id as string ] . isOpen ;
156- }
157-
158- return {
159- order,
160- records,
161- } ;
162- }
163-
164- private createNodeRecord ( data : FixedSizeNodeData < T > ) : FixedSizeNodeRecord < T > {
165- const record : FixedSizeNodeRecord < T > = {
166- data,
167- isOpen : data . isOpenByDefault ,
168- toggle : async ( ) => {
169- record . isOpen = ! record . isOpen ;
170- await this . recomputeTree ( { refreshNodes : record . isOpen } ) ;
171- } ,
172- } ;
173-
174- return record ;
175- }
176173}
0 commit comments