You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/advanced/AsyncActions.md
+62-62Lines changed: 62 additions & 62 deletions
Original file line number
Diff line number
Diff line change
@@ -45,60 +45,60 @@ We’ll use separate types in this tutorial.
45
45
46
46
## Synchronous Action Creators
47
47
48
-
Let’s start by defining the several synchronous action types and action creators we need in our example app. Here, the user can select a reddit to display:
48
+
Let’s start by defining the several synchronous action types and action creators we need in our example app. Here, the user can select a subreddit to display:
49
49
50
50
#### `actions.js`
51
51
52
52
```js
53
-
exportconstSELECT_REDDIT='SELECT_REDDIT'
53
+
exportconstSELECT_SUBREDDIT='SELECT_SUBREDDIT'
54
54
55
-
exportfunctionselectReddit(reddit) {
55
+
exportfunctionselectSubreddit(subreddit) {
56
56
return {
57
-
type:SELECT_REDDIT,
58
-
reddit
57
+
type:SELECT_SUBREDDIT,
58
+
subreddit
59
59
}
60
60
}
61
61
```
62
62
63
63
They can also press a “refresh” button to update it:
These were the actions governed by the user interaction. We will also have another kind of action, governed by the network requests. We will see how to dispatch them later, but for now, we just want to define them.
77
77
78
-
When it’s time to fetch the posts for some reddit, we will dispatch a `REQUEST_POSTS` action:
78
+
When it’s time to fetch the posts for some subreddit, we will dispatch a `REQUEST_POSTS` action:
79
79
80
80
```js
81
81
exportconstREQUEST_POSTS='REQUEST_POSTS'
82
82
83
-
exportfunctionrequestPosts(reddit) {
83
+
exportfunctionrequestPosts(subreddit) {
84
84
return {
85
85
type:REQUEST_POSTS,
86
-
reddit
86
+
subreddit
87
87
}
88
88
}
89
89
```
90
90
91
-
It is important for it to be separate from `SELECT_REDDIT` or `INVALIDATE_REDDIT`. While they may occur one after another, as the app grows more complex, you might want to fetch some data independently of the user action (for example, to prefetch the most popular reddits, or to refresh stale data once in a while). You may also want to fetch in response to a route change, so it’s not wise to couple fetching to some particular UI event early on.
91
+
It is important for it to be separate from `SELECT_SUBREDDIT` or `INVALIDATE_SUBREDDIT`. While they may occur one after another, as the app grows more complex, you might want to fetch some data independently of the user action (for example, to prefetch the most popular subreddits, or to refresh stale data once in a while). You may also want to fetch in response to a route change, so it’s not wise to couple fetching to some particular UI event early on.
92
92
93
93
Finally, when the network request comes through, we will dispatch `RECEIVE_POSTS`:
94
94
95
95
```js
96
96
exportconstRECEIVE_POSTS='RECEIVE_POSTS'
97
97
98
-
exportfunctionreceivePosts(reddit, json) {
98
+
exportfunctionreceivePosts(subreddit, json) {
99
99
return {
100
100
type:RECEIVE_POSTS,
101
-
reddit,
101
+
subreddit,
102
102
posts:json.data.children.map(child=>child.data),
103
103
receivedAt:Date.now()
104
104
}
@@ -109,7 +109,7 @@ This is all we need to know for now. The particular mechanism to dispatch these
109
109
110
110
>##### Note on Error Handling
111
111
112
-
>In a real app, you’d also want to dispatch an action on request failure. We won’t implement error handling in this tutorial, but the [real world example](../introduction/Examples.md#real-world) shows one of the possible approaches.
112
+
>In a real app, you’d also want to dispatch an action on request failure. We won’t implement error handling in this tutorial, but the [real world example](../introduction/Examples.html#real-world) shows one of the possible approaches.
113
113
114
114
## Designing the State Shape
115
115
@@ -123,8 +123,8 @@ Here’s what the state shape for our “Reddit headlines” app might look like
123
123
124
124
```js
125
125
{
126
-
selectedReddit:'frontend',
127
-
postsByReddit: {
126
+
selectedSubreddit:'frontend',
127
+
postsBySubreddit: {
128
128
frontend: {
129
129
isFetching:true,
130
130
didInvalidate:false,
@@ -138,7 +138,7 @@ Here’s what the state shape for our “Reddit headlines” app might look like
138
138
{
139
139
id:42,
140
140
title:'Confusion about Flux and Relay'
141
-
},
141
+
},
142
142
{
143
143
id:500,
144
144
title:'Creating a Simple Application Using React JS and Flux Architecture'
@@ -159,11 +159,11 @@ There are a few important bits here:
159
159
160
160
>In this example, we store the received items together with the pagination information. However, this approach won’t work well if you have nested entities referencing each other, or if you let the user edit items. Imagine the user wants to edit a fetched post, but this post is duplicated in several places in the state tree. This would be really painful to implement.
161
161
162
-
>If you have nested entities, or if you let users edit received entities, you should keep them separately in the state as if it was a database. In pagination information, you would only refer to them by their IDs. This lets you always keep them up to date. The [real world example](../introduction/Examples.md#real-world) shows this approach, together with [normalizr](https://github.com/gaearon/normalizr) to normalize the nested API responses. With this approach, your state might look like this:
162
+
>If you have nested entities, or if you let users edit received entities, you should keep them separately in the state as if it was a database. In pagination information, you would only refer to them by their IDs. This lets you always keep them up to date. The [real world example](../introduction/Examples.html#real-world) shows this approach, together with [normalizr](https://github.com/gaearon/normalizr) to normalize the nested API responses. With this approach, your state might look like this:
163
163
164
164
>```js
165
165
> {
166
-
>selectedReddit:'frontend',
166
+
>selectedSubreddit:'frontend',
167
167
> entities: {
168
168
> users: {
169
169
>2: {
@@ -184,7 +184,7 @@ There are a few important bits here:
184
184
> }
185
185
> }
186
186
> },
187
-
>postsByReddit: {
187
+
>postsBySubreddit: {
188
188
> frontend: {
189
189
> isFetching:true,
190
190
> didInvalidate:false,
@@ -215,14 +215,14 @@ Before going into the details of dispatching actions together with network reque
* We extracted `posts(state, action)` that manages the state of a specific post list. This is just [reducer composition](../basics/Reducers.md#splitting-reducers)! It is our choice how to split the reducer into smaller reducers, and in this case, we’re delegating updating items inside an object to a `posts` reducer. The [real world example](../introduction/Examples.md#real-world) goes even further, showing how to create a reducer factory for parameterized pagination reducers.
295
+
* We extracted `posts(state, action)` that manages the state of a specific post list. This is just [reducer composition](../basics/Reducers.md#splitting-reducers)! It is our choice how to split the reducer into smaller reducers, and in this case, we’re delegating updating items inside an object to a `posts` reducer. The [real world example](../introduction/Examples.html#real-world) goes even further, showing how to create a reducer factory for parameterized pagination reducers.
296
296
297
297
Remember that reducers are just functions, so you can use functional composition and higher-order functions as much as you feel comfortable.
298
298
@@ -310,18 +310,18 @@ We can still define these special thunk action creators inside our `actions.js`
310
310
importfetchfrom'isomorphic-fetch'
311
311
312
312
exportconstREQUEST_POSTS='REQUEST_POSTS'
313
-
functionrequestPosts(reddit) {
313
+
functionrequestPosts(subreddit) {
314
314
return {
315
315
type:REQUEST_POSTS,
316
-
reddit
316
+
subreddit
317
317
}
318
318
}
319
319
320
320
exportconstRECEIVE_POSTS='RECEIVE_POSTS'
321
-
functionreceivePosts(reddit, json) {
321
+
functionreceivePosts(subreddit, json) {
322
322
return {
323
323
type:RECEIVE_POSTS,
324
-
reddit,
324
+
subreddit,
325
325
posts:json.data.children.map(child=>child.data),
326
326
receivedAt:Date.now()
327
327
}
@@ -331,33 +331,33 @@ function receivePosts(reddit, json) {
331
331
// Though its insides are different, you would use it just like any other action creator:
332
332
// store.dispatch(fetchPosts('reactjs'))
333
333
334
-
exportfunctionfetchPosts(reddit) {
334
+
exportfunctionfetchPosts(subreddit) {
335
335
336
336
// Thunk middleware knows how to handle functions.
337
337
// It passes the dispatch method as an argument to the function,
338
338
// thus making it able to dispatch actions itself.
339
339
340
-
returndispatch=> {
340
+
returnfunction (dispatch) {
341
341
342
342
// First dispatch: the app state is updated to inform
343
343
// that the API call is starting.
344
344
345
-
dispatch(requestPosts(reddit))
345
+
dispatch(requestPosts(subreddit))
346
346
347
347
// The function called by the thunk middleware can return a value,
348
348
// that is passed on as the return value of the dispatch method.
349
349
350
350
// In this case, we return a promise to wait for.
351
351
// This is not required by thunk middleware, but it is convenient for us.
>Async action creators are especially convenient for server rendering. You can create a store, dispatch a single async action creator that dispatches other async action creators to fetch data for a whole section of your app, and only render after the Promise it returns completes. Then your store will already be hydrated with the state you need before rendering.
490
+
>Async action creators are especially convenient for server rendering. You can create a store, dispatch a single async action creator that dispatches other async action creators to fetch data for a whole section of your app, and only render after the Promise it returns, completes. Then your store will already be hydrated with the state you need before rendering.
491
491
492
-
[Thunk middleware](https://github.com/gaearon/redux-thunk) isn’t the only way to orchestrate asynchronous actions in Redux. You can use [redux-promise](https://github.com/acdlite/redux-promise) or [redux-promise-middleware](https://github.com/pburtchaell/redux-promise-middleware) to dispatch Promises instead of functions. You can dispatch Observables with [redux-rx](https://github.com/acdlite/redux-rx). You can even write a custom middleware to describe calls to your API, like the [real world example](../introduction/Examples.md#real-world) does. It is up to you to try a few options, choose a convention you like, and follow it, whether with, or without the middleware.
492
+
[Thunk middleware](https://github.com/gaearon/redux-thunk) isn’t the only way to orchestrate asynchronous actions in Redux. You can use [redux-promise](https://github.com/acdlite/redux-promise) or [redux-promise-middleware](https://github.com/pburtchaell/redux-promise-middleware) to dispatch Promises instead of functions. You can dispatch Observables with [redux-rx](https://github.com/acdlite/redux-rx). You can even write a custom middleware to describe calls to your API, like the [real world example](../introduction/Examples.html#real-world) does. It is up to you to try a few options, choose a convention you like, and follow it, whether with, or without the middleware.
0 commit comments