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/src/docs/01-getting-started.md
+1-309Lines changed: 1 addition & 309 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -71,312 +71,4 @@ This is completely optional, but very useful for keeping tracking of dispatched
71
71
72
72
Now that we have our reactor, let's create some actions.
73
73
74
-
## Creating Actions
75
-
76
-
Actions (sometimes called action creators) are functions that you call to send data into the system. In Nuclear, any function that calls
77
-
`reactor.dispatch(actionType: string, payload: any)` is categorized as an action.
78
-
79
-
For our example, we'll start by creating an action to fetch products from a server and another action to add a product to the user's shopping cart.
80
-
81
-
In order to correctly reference actions throughout the system, we'll create an `actionTypes.js` file, which is simply a collection of constants.
82
-
We're using React's keyMirror utility to create the constants, but that's just a convenience — you can create action types in any way you'd like.
83
-
They're not even required to be in a separate file, though that's certainly recommended.
84
-
85
-
#### `actionTypes.js`
86
-
87
-
```javascript
88
-
importkeyMirrorfrom'react/lib/keyMirror'
89
-
90
-
exportdefaultkeyMirror({
91
-
RECEIVE_PRODUCTS:null,
92
-
ADD_TO_CART:null,
93
-
CHECKOUT_START:null,
94
-
CHECKOUT_SUCCESS:null,
95
-
CHECKOUT_FAILED:null,
96
-
})
97
-
```
98
-
99
-
#### `actions.js`
100
-
101
-
```javascript
102
-
importshopfrom'../../common/api/shop'
103
-
importreactorfrom'./reactor'
104
-
import {
105
-
RECEIVE_PRODUCTS,
106
-
ADD_TO_CART,
107
-
CHECKOUT_START,
108
-
CHECKOUT_SUCCESS,
109
-
CHECKOUT_FAILED,
110
-
} from'./actionTypes'
111
-
112
-
exportdefault {
113
-
fetchProducts() {
114
-
shop.getProducts(products=> {
115
-
reactor.dispatch(RECEIVE_PRODUCTS, { products })
116
-
});
117
-
},
118
-
119
-
addToCart(product) {
120
-
reactor.dispatch(ADD_TO_CART, { product })
121
-
},
122
-
}
123
-
```
124
-
125
-
We've now created two actions that we can use to send data into the system.
126
-
127
-
`addToCart` is a simple, synchronous action that takes in a product and dispatches `"ADD_TO_CART"` with the product in the payload.
128
-
129
-
While synchronous actions are great, often you'll need to perform an asynchronous operation before dispatching an action. Nuclear
130
-
fully supports creating actions asynchronously, as we're doing in `fetchProducts`. This is a common pattern you'll use as your application grows,
131
-
and Nuclear has no opinion on how you perform your operations: callbacks, Promises, Generators, ES7 async functions — they'll all work just fine!
132
-
133
-
If you'd like to jump ahead, you can read more about [async actions](./04-async-actions-and-optimistic-updates.html).
134
-
135
-
Now let's build a few stores.
136
-
137
-
## Creating Stores
138
-
139
-
In Flux, stores are used for managing application state, but they don't represent a single record of data like resource models do.
140
-
141
-
More than simply managing ORM-style objects, **stores manage the state for a particular domain within the application**.
142
-
143
-
Unlike many other Flux libraries, Nuclear stores hold no state. Instead, they provide a collection of functions that transform current state into new state.
144
-
145
-
Stores provide a `getInitialState` method, which returns the initial state value that a store will manage, and an `initialize` hook, which is used to define what
146
-
actions a store will respond to by attaching handlers.
147
-
148
-
Each attached handler takes in current state, transforms it according to the action and its payload,
149
-
then returns new state. Handlers have the following signature: `handler(currentState: any, payload: any)`. In Nucler, state can only be an ImmutableJS data type,
150
-
such as an `Immutable.Map` or an `Immutable.List`, or a JavaScript primitive.
151
-
152
-
Because stores in Nuclear don't hold state — they simply receive state, transform it, and return new state — there is no need to worry about stores knowing
153
-
about other stores. That means no confusing `store.waitsFor` and no cross-pollution of data. In Nuclear, the sole responsibility of a store is to return a portion
154
-
of existing or transformed application state. The responsibility of reading application state falls on **Getters**, which we'll cover later.
155
-
156
-
Let's continue by creating stores for managing products and the user's shopping cart. Create a `stores/ProductStore.js` file and a `stores/CartStore.js` file.
Finally, we'll need to register our stores with the reactor we created at the very beginning.
240
-
241
-
Registering the store with a reactor does two things:
242
-
243
-
1. Passes every dispatched action to the store
244
-
2. Binds the state a store manages to the application state by the key used for registration
245
-
246
-
Let's register the stores inside of `main.js`.
247
-
248
-
#### `main.js`
249
-
250
-
```javascript
251
-
importreactorfrom'./reactor'
252
-
importProductStorefrom'./stores/ProductStore'
253
-
importCartStorefrom'./stores/CartStore'
254
-
255
-
reactor.registerStores({
256
-
'products': ProductStore,
257
-
'cart': CartStore,
258
-
})
259
-
```
260
-
261
-
The above stores can be now be accessed with the following keypaths: `['products']` and `['cart']`. We'll cover keypaths in the Getters section.
262
-
263
-
But first, a recap:
264
-
265
-
## Recap
266
-
267
-
At this point we've created actions for fetching products and adding an item to the cart. We also have the `ProductStore` and `CartStore` registered on the reactor.
268
-
269
-
Let's see what our application state looks like by using the `reactor.evaluate` function:
270
-
271
-
```javascript
272
-
// providing an empty array to `evaluate` will return a snapshot of the entire app state
273
-
reactor.evaluate([])
274
-
// result
275
-
Map {
276
-
cart:Map {
277
-
itemQty:Map {}
278
-
},
279
-
products:Map {}
280
-
}
281
-
282
-
// by passing a keypath, `evaluate` will return a more granular piece of app state
283
-
reactor.evaluate(['cart'])
284
-
// result
285
-
Map {
286
-
itemQty:Map {}
287
-
}
288
-
```
289
-
290
-
The application state is rather empty; each top level key is currently populated by its store's `getInitialState()` method.
291
-
292
-
Let's see what our application state looks like after we fetch some products.
293
-
294
-
```javascript
295
-
actions.fetchProducts()
296
-
```
297
-
298
-
After the products have been fetched, our app state looks like this:
Those two things happened, because our store handlers responded to the `addToCart` action and transformed the app state.
340
-
341
-
You might think that the information associated with our stores is pretty minimal. For example, the `CartStore` doesn't actually know anything about the product,
342
-
such as its title, price or images — all information that we'd need if we were to build a cart component. It only knows that there is a mapping between 3 and 1,
343
-
which refers to `<id> => <qty>`.
344
-
345
-
Minimal data management within our stores is in fact a good practice, because it helps encapsulate and minimize the scope of data management for a particular store.
346
-
Remember, each store is supposed to manages only a single particular domain. In the case of the `CartStore`, it only cares about item quantities, so it doesn't need
347
-
anything more than an item's id and its quantity count.
348
-
349
-
However, if stores are limited in scope, how can you read substantive data from the app state?
350
-
351
-
It's actually quite simple: **composition**.
352
-
353
-
Nuclear allows you to combine data from stores in a non-destructive manner, check it out:
0 commit comments