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
@@ -19,30 +19,6 @@ You might wonder why **undefined** is not part of the core value types. Well, th
19
19
1. It is not a serializable value. That means if you explicitly set a value to _undefined_ it will not show up in the devtools
20
20
2. Undefined values can not be tracked. That means if you were to iterate an object and look at the keys of that object, any undefined values will not be tracked. This can cause unexpected behaviour
21
21
22
-
{% hint style="info" %}
23
-
When writing Typescript you should **not** use optional values for your state \(**?**\), or use **undefined** in a union type. In a serializable state store world **null** is the value indicating _“there is no value”_.
24
-
25
-
```typescript
26
-
typeState= {
27
-
// Do not do this
28
-
foo?:string
29
-
30
-
// Do not do this
31
-
foo:string|undefined
32
-
33
-
// Do this
34
-
foo:string|null
35
-
36
-
// Or this, if there always will be a value there
37
-
foo:string
38
-
}
39
-
40
-
exportconst state:State= {
41
-
foo: null
42
-
}
43
-
```
44
-
{% endhint %}
45
-
46
22
### Naming
47
23
48
24
Each value needs to sit behind a name. Naming can be difficult, but we have some help. Even though we eventually do want to consume our application through a user interface we ideally want to avoid naming things specifically related to the environment where we show the user interface. Things like **page**, **tabs**, **modal** etc. are specific to a browser experience, maybe related to a certain size. We want to avoid those names as they should not dictate which elements are to be used with the state, that is up to the user interface to decide later. So here are some generic terms to use instead:
@@ -55,7 +31,7 @@ Each value needs to sit behind a name. Naming can be difficult, but we have some
55
31
56
32
The root value of your state tree is an object, because objects are great for holding other values. An object has keys that point to values. Most of these keys point to values that are the actual state of the application, but these keys can also represent domains of the application. A typical state structure could be:
57
33
58
-
```typescript
34
+
```javascript
59
35
{
60
36
modes: ['issues', 'admin'],
61
37
currentModeIndex:0,
@@ -84,7 +60,7 @@ Arrays are similar to objects in the sense that they hold other values, but inst
84
60
85
61
Strings are of course used to represent text values. Names, descriptions and whatnot. But strings are also used for ids, types, etc. Strings can be used as values to reference other values. This is an important part in structuring state. For example in our **objects** example above we chose to use an array to represent the modes, using an index to point to the current mode, but we could also do:
86
62
87
-
```typescript
63
+
```javascript
88
64
{
89
65
modes: {
90
66
issues:0,
@@ -115,53 +91,38 @@ All values, with the exception of booleans, can also be **null**. Non-existing.
115
91
116
92
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.
117
93
118
-
{% code title="overmind/state.ts" %}
119
-
```typescript
120
-
exporttypeUser= {
121
-
id:number
122
-
firstName:string
123
-
lastName:string
124
-
readonly fullName:string
125
-
}
126
-
127
-
exporttypeState= {
128
-
user:User
129
-
}
130
-
131
-
exportconst state:State= {
94
+
{% tabs %}
95
+
{% tab title="overmind/state.js" %}
96
+
```javascript
97
+
exportconststate= {
132
98
user: {
133
99
id:1,
134
100
firstName:'Bob',
135
101
lastName:'Jackson',
136
-
get fullName(this:User) {
137
-
returnthis.firstName+''+this.lastName
138
-
}
102
+
jwt:'1234567'
103
+
},
104
+
getisLoggedIn() {
105
+
returnBoolean(this.user&&this.user.jwt)
139
106
}
140
107
}
141
108
```
142
-
{% endcode %}
109
+
{% endtab %}
110
+
{% endtabs %}
143
111
144
112
### Cached getter
145
113
146
114
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:
147
115
116
+
{% tabs %}
117
+
{% tab title="overmind/state.js" %}
148
118
```typescript
149
-
import { Derive } from'overmind'
150
-
151
-
exporttypeState= {
152
-
title:string
153
-
upperTitle:Derive<State, string>
154
-
}
155
-
156
119
exportconst state:State= {
157
120
title: 'My awesome title',
158
121
upperTitle: state=>state.title.toUpperCase()
159
122
}
160
123
```
161
-
162
-
{% hint style="info" %}
163
-
Is is important that you define your state with a **type**, do **NOT** use an **interface**
164
-
{% endhint %}
124
+
{% endtab %}
125
+
{% endtabs %}
165
126
166
127
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:
167
128
@@ -176,31 +137,20 @@ Even though derived state is defined as functions you consume them as plain valu
176
137
177
138
### Dynamic getter
178
139
179
-
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. For example you want to be able to select records in a table and calculate some data based on that:
180
-
181
-
{% code title="overmind/state.ts" %}
182
-
```typescript
183
-
import { Derive } from'overmind'
140
+
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:
For scalability you can define **namespaces** for multiple configurations. Read more about that in [Structuring the app](../guides-1/structuring-the-app.md)
244
+
{% endhint %}
245
+
333
246
## Summary
334
247
335
248
This short guide gave you some insight into how we think about state and what state really is in an application. There is more to learn about these values and how to use them to describe the application. Please move on to other guides to learn more.
0 commit comments