1
1
import * as React from 'react'
2
- import { runInAction } from 'mobx'
3
- import { RSQLStore } from 'models/rsql'
2
+ import { Loading } from './loading'
4
3
const request = require ( 'utils/request' ) . default
5
4
const queryParams = require ( 'utils/queryParams' ) . default
6
- const each = require ( 'utils/each' ) . default
7
5
8
6
const ENDPOINT = '/api/sql'
9
7
10
8
interface Props {
11
- variables : any
12
- children : ( params : any ) => any
13
- store : RSQLStore
14
- queries : any
9
+ queries : any [ ]
10
+ children : ( data : any [ ] , totals ?: number [ ] , loadMores ?: boolean [ ] ) => any
11
+ variables ?: any
12
+ mapData ?: ( data : any [ ] ) => any [ ]
13
+ loading ?: React . ReactNode
15
14
}
16
15
17
16
export class RsqlFetcher extends React . Component < Props > {
@@ -23,19 +22,29 @@ export class RsqlFetcher extends React.Component<Props> {
23
22
24
23
state = {
25
24
variables : this . props . variables ,
26
- data : { } ,
25
+ data : [ ] ,
26
+ totals : [ ] ,
27
+ loadMores : [ ] ,
28
+ fetching : true ,
29
+ }
30
+
31
+ componentDidMount ( ) {
32
+ this . fetchData ( )
27
33
}
28
34
29
35
render ( ) {
30
- return this . props . children ( this . state . data )
36
+ if ( this . state . fetching ) {
37
+ return this . props . loading || < Loading />
38
+ }
39
+
40
+ return this . props . children ( this . state . data , this . state . totals , this . state . loadMores )
31
41
}
32
42
33
- async fetchData ( ) {
34
- const store : RSQLStore = this . props . store
43
+ async fetchData ( fetching = true ) {
35
44
const variables = this . state . variables
36
45
const promiseList = [ ]
37
46
const totalsPromiseList = [ ]
38
- store . setFetching ( true )
47
+ this . setState ( { fetching } )
39
48
40
49
for ( let q of this . props . queries ) {
41
50
const query = q . query ( variables )
@@ -44,10 +53,10 @@ export class RsqlFetcher extends React.Component<Props> {
44
53
query . limit += offset
45
54
}
46
55
47
- const promise = request ( `${ ENDPOINT } ?${ queryParams ( query ) } ` ) . then ( ( data : any [ ] ) => ( { key : q . prop , data } ) )
56
+ const promise = request ( `${ ENDPOINT } ?${ queryParams ( query ) } ` )
48
57
promiseList . push ( promise )
49
58
50
- if ( q . pagination && store . setTotal ) {
59
+ if ( q . pagination ) {
51
60
const totalParams = queryParams ( {
52
61
fields : [ 'COUNT(*) as count' ] ,
53
62
table : query . table ,
@@ -59,14 +68,14 @@ export class RsqlFetcher extends React.Component<Props> {
59
68
}
60
69
}
61
70
62
- const result : any = await Promise . all ( promiseList )
63
- const totals : any = await Promise . all ( totalsPromiseList )
64
- runInAction ( 'set book data' , ( ) => {
65
- each ( result , ( qr : any ) => store . setData ( qr . key , qr . data ) )
66
- each ( totals , ( tr : any ) => store . setTotal ( tr . key , tr . count ) )
67
- store . setFetching ( false )
68
- this . setState ( { } )
69
- } )
71
+ let data : any = await Promise . all ( promiseList )
72
+ const totals : any = await Promise . all ( totalsPromiseList ) . then ( result => result . map ( r => r ?. count ?? 0 ) )
73
+
74
+ if ( this . props . mapData ) {
75
+ data = this . props . mapData ( data )
76
+ }
77
+
78
+ this . setState ( { data , totals , fetching : false } )
70
79
}
71
80
72
81
setVariables ( newVariables : any ) {
@@ -76,28 +85,51 @@ export class RsqlFetcher extends React.Component<Props> {
76
85
}
77
86
78
87
async loadMore ( type : string , count : number = 20 ) {
79
- const store : RSQLStore = this . props . store
80
88
const variables = this . state . variables
89
+ const index = this . getIndex ( type )
81
90
82
- const q = this . props . queries . find ( q => q . prop === type )
91
+ if ( index < 0 ) return
92
+ const q = this . props . queries [ index ]
83
93
84
- if ( ! q ) {
85
- return
86
- }
87
- store . setLoadMore ( type , true )
94
+ this . setLoadMore ( index , true )
88
95
89
96
const query = q . query ( variables )
90
97
let offset = ( this . offsets [ q . prop ] || 0 ) as number
91
- query . offset = ( store as any ) [ type ] . length
98
+ query . offset = this . state . data [ index ] . length
92
99
query . limit = count
93
100
this . offsets [ q . prop ] = offset + count
94
101
95
- const result = await request ( `${ ENDPOINT } ?${ queryParams ( query ) } ` )
102
+ const data = await request ( `${ ENDPOINT } ?${ queryParams ( query ) } ` )
96
103
97
- runInAction ( ( ) => {
98
- store . appendData ( q . prop , result )
99
- store . setLoadMore ( type , false )
100
- this . setState ( { } )
101
- } )
104
+ this . appendData ( index , data )
105
+ this . setLoadMore ( index , false )
106
+ }
107
+
108
+ getData ( prop : string ) {
109
+ return this . state . data [ this . getIndex ( prop ) ]
110
+ }
111
+
112
+ updateData ( prop : string , data ) {
113
+ this . state . data [ this . getIndex ( prop ) ] = data
114
+
115
+ this . setState ( { data : [ ...this . state . data ] } )
116
+ }
117
+
118
+ private getIndex ( prop : string ) {
119
+ return this . props . queries . findIndex ( q => q . prop === prop )
120
+ }
121
+
122
+ private setLoadMore ( index : number , value : boolean ) {
123
+ const loadMores = [ ...this . state . loadMores ]
124
+ loadMores [ index ] = value
125
+
126
+ this . setState ( { loadMores } )
127
+ }
128
+
129
+ private appendData ( index : number , data : any [ ] ) {
130
+ const result = [ ...this . state . data ]
131
+ result [ index ] = result [ index ] . concat ( data )
132
+
133
+ this . setState ( { data : result } )
102
134
}
103
135
}
0 commit comments