Skip to content

Commit a4cfbb7

Browse files
christianalfonigitbook-bot
authored andcommitted
GitBook: [master] one page modified
1 parent 0728fd9 commit a4cfbb7

File tree

1 file changed

+67
-67
lines changed

1 file changed

+67
-67
lines changed

core/defining-state.md

Lines changed: 67 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,73 @@ export const updateState = ({ state }) => {
269269
Note that **rehydrate** gives you full type safety when adding the **SERIALIZE** symbol to your classes. This is a huge benefit as Typescript will yell at you when the state structure changes, related to the rehydration
270270
{% endhint %}
271271

272+
## Deriving state
273+
274+
### Getter
275+
276+
A concept in Javascript called a [GETTER](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get) allows you to intercept accessing a property in an object. A getter is just like a plain value, it can be added or removed at any point. Getters do **not** cache the result for that very reason, but whatever state they access is tracked.
277+
278+
{% tabs %}
279+
{% tab title="overmind/state.js" %}
280+
```javascript
281+
export const state = {
282+
user: {
283+
id: 1,
284+
firstName: 'Bob',
285+
lastName: 'Jackson',
286+
jwt: '1234567'
287+
},
288+
get isLoggedIn() {
289+
return Boolean(this.user && this.user.jwt)
290+
}
291+
}
292+
```
293+
{% endtab %}
294+
{% endtabs %}
295+
296+
### Cached getter
297+
298+
When you need to do more heavy calculation or combine state from different parts of the tree you can use a plain function instead. Overmind treats these functions like a **getter**, but the returned value is cached and they can also access the root state of the application. A simple example of this would be:
299+
300+
{% tabs %}
301+
{% tab title="overmind/state.js" %}
302+
```typescript
303+
export const state: State = {
304+
title: 'My awesome title',
305+
upperTitle: state => state.title.toUpperCase()
306+
}
307+
```
308+
{% endtab %}
309+
{% endtabs %}
310+
311+
The first argument of the function is the state the derived function is attached to. A second argument is also passed and that is the root state of the application, allowing you to access whatever you would need. Two important traits of the derived function is:
312+
313+
1. The state accessed is tracked
314+
2. The value returned is cached
315+
316+
That means the function only runs when accessed and the depending state has changed since last access.
317+
318+
{% hint style="info" %}
319+
Even though derived state is defined as functions you consume them as plain values. You do not have to call the derived function to get the value. Derived state can not be dynamically added. They have to be defined and live in the tree from start to end of your application lifecycle.
320+
{% endhint %}
321+
322+
### Dynamic getter
323+
324+
Sometimes you want to derive state based on some value coming from the user interface. You can do this by creating a function that returns a function. This can be useful for helper functions:
325+
326+
{% tabs %}
327+
{% tab title="overmind/state.js" %}
328+
```javascript
329+
export const state = {
330+
users: {},
331+
userById: ({ users }) => id => users[id]
332+
}
333+
334+
// state.userById('123')
335+
```
336+
{% endtab %}
337+
{% endtabs %}
338+
272339
## Statemachines
273340

274341
Very often you get into a situation where you define states as **isLoading**, **hasError** etc. Having these kinds of state can cause **impossible states**. For example:
@@ -396,73 +463,6 @@ You can reset the state of a statemachine, which also runs the exit of the curre
396463
state.mode.reset()
397464
```
398465

399-
## Deriving state
400-
401-
### Getter
402-
403-
A concept in Javascript called a [GETTER](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get) allows you to intercept accessing a property in an object. A getter is just like a plain value, it can be added or removed at any point. Getters do **not** cache the result for that very reason, but whatever state they access is tracked.
404-
405-
{% tabs %}
406-
{% tab title="overmind/state.js" %}
407-
```javascript
408-
export const state = {
409-
user: {
410-
id: 1,
411-
firstName: 'Bob',
412-
lastName: 'Jackson',
413-
jwt: '1234567'
414-
},
415-
get isLoggedIn() {
416-
return Boolean(this.user && this.user.jwt)
417-
}
418-
}
419-
```
420-
{% endtab %}
421-
{% endtabs %}
422-
423-
### Cached getter
424-
425-
When you need to do more heavy calculation or combine state from different parts of the tree you can use a plain function instead. Overmind treats these functions like a **getter**, but the returned value is cached and they can also access the root state of the application. A simple example of this would be:
426-
427-
{% tabs %}
428-
{% tab title="overmind/state.js" %}
429-
```typescript
430-
export const state: State = {
431-
title: 'My awesome title',
432-
upperTitle: state => state.title.toUpperCase()
433-
}
434-
```
435-
{% endtab %}
436-
{% endtabs %}
437-
438-
The first argument of the function is the state the derived function is attached to. A second argument is also passed and that is the root state of the application, allowing you to access whatever you would need. Two important traits of the derived function is:
439-
440-
1. The state accessed is tracked
441-
2. The value returned is cached
442-
443-
That means the function only runs when accessed and the depending state has changed since last access.
444-
445-
{% hint style="info" %}
446-
Even though derived state is defined as functions you consume them as plain values. You do not have to call the derived function to get the value. Derived state can not be dynamically added. They have to be defined and live in the tree from start to end of your application lifecycle.
447-
{% endhint %}
448-
449-
### Dynamic getter
450-
451-
Sometimes you want to derive state based on some value coming from the user interface. You can do this by creating a function that returns a function. This can be useful for helper functions:
452-
453-
{% tabs %}
454-
{% tab title="overmind/state.js" %}
455-
```javascript
456-
export const state = {
457-
users: {},
458-
userById: ({ users }) => id => users[id]
459-
}
460-
461-
// state.userById('123')
462-
```
463-
{% endtab %}
464-
{% endtabs %}
465-
466466
## References
467467

468468
When you add objects and arrays to your state tree, they are labeled with an “address” in the tree. That means if you try to add the same object or array in multiple spots in the tree you will get an error, as they can not have multiple addresses. Typically this indicates that you’d rather want to create a reference to an existing object or array.

0 commit comments

Comments
 (0)