Browse Source

Improved flow type checking

Arnaud Vergnet 4 years ago
parent
commit
433306e2a7
1 changed files with 61 additions and 71 deletions
  1. 61
    71
      src/components/Screens/WebSectionList.js

+ 61
- 71
src/components/Screens/WebSectionList.js View File

@@ -10,26 +10,28 @@ import BasicLoadingScreen from "./BasicLoadingScreen";
10 10
 import {withCollapsible} from "../../utils/withCollapsible";
11 11
 import * as Animatable from 'react-native-animatable';
12 12
 import CustomTabBar from "../Tabbar/CustomTabBar";
13
+import {Collapsible} from "react-navigation-collapsible";
13 14
 
14 15
 type Props = {
15
-    navigation: Object,
16
+    navigation: { [key: string]: any },
16 17
     fetchUrl: string,
17 18
     autoRefreshTime: number,
18 19
     refreshOnFocus: boolean,
19
-    renderItem: React.Node,
20
-    renderSectionHeader: React.Node,
21
-    stickyHeader: boolean,
22
-    createDataset: Function,
23
-    updateData: number,
24
-    itemHeight: number | null,
25
-    onScroll: Function,
26
-    collapsibleStack: Object,
20
+    renderItem: (data: { [key: string]: any }) => React.Node,
21
+    createDataset: (data: { [key: string]: any }) => Array<Object>,
22
+    onScroll: (event: SyntheticEvent<EventTarget>) => void,
23
+    collapsibleStack: Collapsible,
24
+
25
+    itemHeight?: number,
26
+    updateData?: number,
27
+    renderSectionHeader?: (data: { [key: string]: any }) => React.Node,
28
+    stickyHeader?: boolean,
27 29
 }
28 30
 
29 31
 type State = {
30 32
     refreshing: boolean,
31 33
     firstLoading: boolean,
32
-    fetchedData: ?Object,
34
+    fetchedData: { [key: string]: any } | null,
33 35
     snackbarVisible: boolean
34 36
 };
35 37
 
@@ -45,37 +47,21 @@ const MIN_REFRESH_TIME = 5 * 1000;
45 47
 class WebSectionList extends React.PureComponent<Props, State> {
46 48
 
47 49
     static defaultProps = {
48
-        renderSectionHeader: null,
49 50
         stickyHeader: false,
50 51
         updateData: 0,
51
-        itemHeight: null,
52 52
     };
53 53
 
54
-    scrollRef: Object;
54
+    scrollRef: { current: null | Animated.SectionList };
55 55
     refreshInterval: IntervalID;
56
-    lastRefresh: Date;
56
+    lastRefresh: Date | null;
57 57
 
58 58
     state = {
59 59
         refreshing: false,
60 60
         firstLoading: true,
61
-        fetchedData: undefined,
61
+        fetchedData: null,
62 62
         snackbarVisible: false
63 63
     };
64 64
 
65
-    onRefresh: Function;
66
-    onFetchSuccess: Function;
67
-    onFetchError: Function;
68
-    getEmptySectionHeader: Function;
69
-
70
-    constructor() {
71
-        super();
72
-        // creating references to functions used in render()
73
-        this.onRefresh = this.onRefresh.bind(this);
74
-        this.onFetchSuccess = this.onFetchSuccess.bind(this);
75
-        this.onFetchError = this.onFetchError.bind(this);
76
-        this.getEmptySectionHeader = this.getEmptySectionHeader.bind(this);
77
-    }
78
-
79 65
     /**
80 66
      * Registers react navigation events on first screen load.
81 67
      * Allows to detect when the screen is focused
@@ -87,13 +73,14 @@ class WebSectionList extends React.PureComponent<Props, State> {
87 73
         this.props.navigation.addListener('blur', onScreenBlur);
88 74
         this.scrollRef = React.createRef();
89 75
         this.onRefresh();
76
+        this.lastRefresh = null;
90 77
     }
91 78
 
92 79
     /**
93 80
      * Refreshes data when focusing the screen and setup a refresh interval if asked to
94 81
      */
95 82
     onScreenFocus() {
96
-        if (this.props.refreshOnFocus && this.lastRefresh !== undefined)
83
+        if (this.props.refreshOnFocus && this.lastRefresh)
97 84
             this.onRefresh();
98 85
         if (this.props.autoRefreshTime > 0)
99 86
             this.refreshInterval = setInterval(this.onRefresh, this.props.autoRefreshTime)
@@ -115,36 +102,37 @@ class WebSectionList extends React.PureComponent<Props, State> {
115 102
      *
116 103
      * @param fetchedData The newly fetched data
117 104
      */
118
-    onFetchSuccess(fetchedData: Object) {
105
+    onFetchSuccess = (fetchedData: { [key: string]: any }) => {
119 106
         this.setState({
120 107
             fetchedData: fetchedData,
121 108
             refreshing: false,
122 109
             firstLoading: false
123 110
         });
124 111
         this.lastRefresh = new Date();
125
-    }
112
+    };
126 113
 
127 114
     /**
128 115
      * Callback used when fetch encountered an error.
129 116
      * It will reset the displayed data and show an error.
130 117
      */
131
-    onFetchError() {
118
+    onFetchError = () => {
132 119
         this.setState({
133
-            fetchedData: undefined,
120
+            fetchedData: null,
134 121
             refreshing: false,
135 122
             firstLoading: false
136 123
         });
137 124
         this.showSnackBar();
138
-    }
125
+    };
139 126
 
140 127
     /**
141 128
      * Refreshes data and shows an animations while doing it
142 129
      */
143
-    onRefresh() {
130
+    onRefresh = () => {
144 131
         let canRefresh;
145
-        if (this.lastRefresh !== undefined)
146
-            canRefresh = (new Date().getTime() - this.lastRefresh.getTime()) > MIN_REFRESH_TIME;
147
-        else
132
+        if (this.lastRefresh != null) {
133
+            const last = this.lastRefresh;
134
+            canRefresh = (new Date().getTime() - last.getTime()) > MIN_REFRESH_TIME;
135
+        } else
148 136
             canRefresh = true;
149 137
         if (canRefresh) {
150 138
             this.setState({refreshing: true});
@@ -152,17 +140,7 @@ class WebSectionList extends React.PureComponent<Props, State> {
152 140
                 .then(this.onFetchSuccess)
153 141
                 .catch(this.onFetchError);
154 142
         }
155
-    }
156
-
157
-    /**
158
-     * Gets an empty section header
159
-     *
160
-     * @param section The current section
161
-     * @return {*}
162
-     */
163
-    getEmptySectionHeader({section}: Object) {
164
-        return <View/>;
165
-    }
143
+    };
166 144
 
167 145
     /**
168 146
      * Shows the error popup
@@ -174,25 +152,38 @@ class WebSectionList extends React.PureComponent<Props, State> {
174 152
      */
175 153
     hideSnackBar = () => this.setState({snackbarVisible: false});
176 154
 
177
-    itemLayout = (data: Object, index: number) => ({
178
-        length: this.props.itemHeight,
179
-        offset: this.props.itemHeight * index,
180
-        index
181
-    });
155
+    itemLayout = (data: { [key: string]: any }, index: number) => {
156
+        const height = this.props.itemHeight;
157
+        if (height == null)
158
+            return undefined;
159
+        return {
160
+            length: height,
161
+            offset: height * index,
162
+            index
163
+        }
164
+    };
182 165
 
183
-    renderSectionHeader = (data: Object) => {
184
-        return (
185
-            <Animatable.View
186
-                animation={"fadeInUp"}
187
-                duration={500}
188
-                useNativeDriver
189
-            >
190
-                {this.props.renderSectionHeader(data)}
191
-            </Animatable.View>
192
-        );
166
+    renderSectionHeader = (data: { section: { [key: string]: any } }) => {
167
+        if (this.props.renderSectionHeader != null) {
168
+            return (
169
+                <Animatable.View
170
+                    animation={"fadeInUp"}
171
+                    duration={500}
172
+                    useNativeDriver
173
+                >
174
+                    {this.props.renderSectionHeader(data)}
175
+                </Animatable.View>
176
+            );
177
+        } else
178
+            return null;
193 179
     }
194 180
 
195
-    renderItem = (data: Object) => {
181
+    renderItem = (data: {
182
+        item: { [key: string]: any },
183
+        index: number,
184
+        section: { [key: string]: any },
185
+        separators: { [key: string]: any },
186
+    }) => {
196 187
         return (
197 188
             <Animatable.View
198 189
                 animation={"fadeInUp"}
@@ -204,16 +195,15 @@ class WebSectionList extends React.PureComponent<Props, State> {
204 195
         );
205 196
     }
206 197
 
207
-    onScroll = (event: Object) => {
198
+    onScroll = (event: SyntheticEvent<EventTarget>) => {
208 199
         if (this.props.onScroll)
209 200
             this.props.onScroll(event);
210 201
     }
211 202
 
212 203
     render() {
213 204
         let dataset = [];
214
-        if (this.state.fetchedData !== undefined)
205
+        if (this.state.fetchedData != null)
215 206
             dataset = this.props.createDataset(this.state.fetchedData);
216
-        const shouldRenderHeader = this.props.renderSectionHeader !== null;
217 207
         const {containerPaddingTop, scrollIndicatorInsetTop, onScrollWithListener} = this.props.collapsibleStack;
218 208
         return (
219 209
             <View>
@@ -230,7 +220,7 @@ class WebSectionList extends React.PureComponent<Props, State> {
230 220
                         />
231 221
                     }
232 222
                     //$FlowFixMe
233
-                    renderSectionHeader={shouldRenderHeader ? this.renderSectionHeader : this.getEmptySectionHeader}
223
+                    renderSectionHeader={this.renderSectionHeader}
234 224
                     //$FlowFixMe
235 225
                     renderItem={this.renderItem}
236 226
                     stickySectionHeadersEnabled={this.props.stickyHeader}
@@ -242,7 +232,7 @@ class WebSectionList extends React.PureComponent<Props, State> {
242 232
                             errorCode={ERROR_TYPE.CONNECTION_ERROR}
243 233
                             onRefresh={this.onRefresh}/>
244 234
                     }
245
-                    getItemLayout={this.props.itemHeight !== null ? this.itemLayout : undefined}
235
+                    getItemLayout={this.props.itemHeight != null ? this.itemLayout : undefined}
246 236
                     // Animations
247 237
                     onScroll={onScrollWithListener(this.onScroll)}
248 238
                     contentContainerStyle={{

Loading…
Cancel
Save