1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
API: `AsyncState` (mixin)
=========================
A mixin for route handlers that fetch at least part of their state
asynchronously.
Static Lifecycle Methods
------------------------
### `getInitialAsyncState(params, query, setState)`
Fetches state for a component after it mounts. Much like the familiar
`getInitialState` method, `getInitialAsyncState` should return a hash of
key/value pairs to use in the component's state. The difference is that
the values may be promises. As these values resolve, the component's
state is updated.
#### Parameters
##### params (object)
The url parameters.
##### query (object)
The url query parameters
##### setState (function)
A function that can be used to `setState` as it is received, useful for
things like `xhr` progress and streamed data. Typically you won't use
this.
Props
-----
### `initialAsyncState`
When testing, use the `initialAsyncState` prop to simulate asynchronous
data fetching. When this prop is present, no attempt is made to retrieve
additional state via `getInitialAsyncState`.
Examples
--------
In it simplest form, just return a hash of promises, they become state:
```js
var User = React.createClass({
mixins: [ Router.AsyncState ],
statics: {
getInitialAsyncState: function (params, query, setState) {
return {
user: fetchUser(params.userId),
activity: fetchActivityForUser(params.userId)
}
}
},
render: function() {
return this.state.user ?
<LoadingUserProfile/> :
<UserProfile user={this.state.user} activity={this.state.activity} />;
}
});
```
But you can get fancier...
```js
var User = React.createClass({
mixins: [ Router.AsyncState ],
statics: {
getInitialAsyncState: function (params, query, setState) {
var buffer = '';
return {
user: getUserByID(params.userID) // may be a promise
activity: {}, // an immediate value (not a promise)
stream: getStreamingData(params.userID, function (chunk) {
// `getStreamingData` returns a promise, but also calls back as
// data is received, giving us a chance to update the UI with
// progress using the `AsyncState` specific `setState`
// function
buffer += chunk;
setState({ streamBuffer: buffer });
})
};
}
},
getInitialState: function () {
return {
user: null, // Receives a value when getUserByID resolves.
stream: null, // Receives a value when getStreamingData resolves.
streamBuffer: '' // Used to track data as it loads.
};
},
render: function () {
if (!this.state.user)
return <LoadingUser/>;
return (
<div>
<p>Welcome {this.state.user.name}!</p>
<p>So far, you've received {this.state.streamBuffer.length} data!</p>
</div>
);
}
});
```
|