@@ -12,13 +12,22 @@ import Spinner from '../../../shared/Spinner';
12
12
import Dropdown from '../../../shared/Dropdown' ;
13
13
import Icon from '../../../shared/Icon' ;
14
14
import Badge from '../../../shared/Badge' ;
15
- import CachedStateWrapper from '../../../../lib/CachedStateWrapper' ;
16
15
17
16
import Build from './build' ;
18
17
import DropdownButton from './../dropdown-button' ;
19
18
19
+ type ViewerPartial = {
20
+ scheduledBuilds : {
21
+ count : number
22
+ } ,
23
+ runningBuilds : {
24
+ count : number
25
+ } ,
26
+ user : Object
27
+ } ;
28
+
20
29
type Props = {
21
- viewer ?: Object ,
30
+ viewer ?: ViewerPartial ,
22
31
relay : Object
23
32
} ;
24
33
@@ -29,27 +38,25 @@ type State = {
29
38
} ;
30
39
31
40
class MyBuilds extends React . Component < Props , State > {
32
- state = {
33
- isDropdownVisible : false ,
34
- scheduledBuildsCount : (
35
- ( this . props . viewer && this . props . viewer . scheduledBuilds )
36
- ? this . props . viewer . scheduledBuilds . count
37
- : 0
38
- ) ,
39
- runningBuildsCount : (
40
- ( this . props . viewer && this . props . viewer . runningBuilds )
41
- ? this . props . viewer . runningBuilds . count
42
- : 0
43
- )
44
- }
41
+ constructor ( props ) {
42
+ super ( props ) ;
43
+
44
+ // When the MyBuilds starts, see if we've got either cached or
45
+ // current build numbers so we can show something right away.
46
+ const initialState = {
47
+ isDropdownVisible : false ,
48
+ scheduledBuildsCount : (
49
+ ( this . props . viewer && this . props . viewer . scheduledBuilds )
50
+ ? this . props . viewer . scheduledBuilds . count
51
+ : 0
52
+ ) ,
53
+ runningBuildsCount : (
54
+ ( this . props . viewer && this . props . viewer . runningBuilds )
55
+ ? this . props . viewer . runningBuilds . count
56
+ : 0
57
+ )
58
+ } ;
45
59
46
- getCachedState ;
47
- setCachedState ;
48
-
49
- // When the MyBuilds mounts, we should see if we've got any cached
50
- // builds numbers so we can show something right away.
51
- componentWillMount ( ) {
52
- const initialState = { } ;
53
60
const cachedState = this . getCachedState ( ) ;
54
61
55
62
if ( ! this . props . viewer || ! this . props . viewer . scheduledBuilds ) {
@@ -60,7 +67,28 @@ class MyBuilds extends React.Component<Props, State> {
60
67
initialState . runningBuildsCount = cachedState . runningBuildsCount || 0 ;
61
68
}
62
69
63
- this . setState ( initialState ) ;
70
+ this . state = initialState ;
71
+ }
72
+
73
+ // NOTE: the localStorage key is 'CachedState:MyBuilds:' for backwards
74
+ // compatibility with data stored by the CachedStateWrapper this used to use.
75
+ getCachedState ( ) {
76
+ const { state , expiresAt } = JSON . parse ( localStorage [ 'CachedState:MyBuilds:' ] || '{}' ) ;
77
+
78
+ if ( ! state || ( expiresAt && expiresAt < Date . now ( ) ) ) {
79
+ return { } ;
80
+ }
81
+
82
+ return state ;
83
+ }
84
+
85
+ setCachedState ( state = { } ) {
86
+ this . setState ( state , ( ) => {
87
+ localStorage [ 'CachedState:MyBuilds:' ] = JSON . stringify ( {
88
+ state,
89
+ expiresAt : Date . now ( ) + hour . bind ( 1 )
90
+ } ) ;
91
+ } ) ;
64
92
}
65
93
66
94
componentDidMount ( ) {
@@ -85,17 +113,31 @@ class MyBuilds extends React.Component<Props, State> {
85
113
// As we get new values for scheduledBuildsCount and runningBuildsCount from
86
114
// Relay + GraphQL, we'll be sure to update the cached state with the latest
87
115
// values so when the page re-loads, we can show the latest numbers.
88
- componentWillReceiveProps ( nextProps ) {
89
- if ( ! nextProps . viewer ) {
116
+ componentDidUpdate ( prevProps : { viewer ?: ViewerPartial } ) {
117
+ const { viewer } = this . props ;
118
+ const { viewer : prevViewer } = prevProps ;
119
+
120
+ // If we don't have a current Viewer object, we know we don't have fresh data
121
+ if ( ! viewer ) {
90
122
return ;
91
123
}
92
124
93
- if ( nextProps . viewer . scheduledBuilds || nextProps . viewer . runningBuilds ) {
94
- this . setCachedState ( {
95
- scheduledBuildsCount : nextProps . viewer . scheduledBuilds . count ,
96
- runningBuildsCount : nextProps . viewer . runningBuilds . count
97
- } ) ;
125
+ // If we have a previous viewer object with build data, let's
126
+ // check if any of the counts have changed, and abort if not
127
+ if ( prevViewer && prevViewer . scheduledBuilds && prevViewer . runningBuilds ) {
128
+ if (
129
+ viewer . scheduledBuilds . count === prevViewer . scheduledBuilds . count &&
130
+ viewer . runningBuilds . count === prevViewer . runningBuilds . count
131
+ ) {
132
+ return ;
133
+ }
98
134
}
135
+
136
+ // Finally, update the state
137
+ this . setCachedState ( {
138
+ scheduledBuildsCount : viewer . scheduledBuilds . count ,
139
+ runningBuildsCount : viewer . runningBuilds . count
140
+ } ) ;
99
141
}
100
142
101
143
render ( ) {
@@ -243,11 +285,7 @@ class MyBuilds extends React.Component<Props, State> {
243
285
} ;
244
286
}
245
287
246
- // Wrap the MyBuilds in a CachedStateWrapper so we get access to methods
247
- // like `setCachedState`
248
- const CachedMyBuilds = CachedStateWrapper ( MyBuilds , { validLength : hour . bind ( 1 ) } ) ;
249
-
250
- export default Relay . createContainer ( CachedMyBuilds , {
288
+ export default Relay . createContainer ( MyBuilds , {
251
289
initialVariables : {
252
290
includeBuilds : false ,
253
291
includeBuildCounts : false
0 commit comments