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: README.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,6 +6,8 @@ description: frictionless state management
6
6
7
7
> Web application development is about **defining**, **changing** and **consuming state** to produce a user experience. Overmind aims for a developer experience where that is all you focus on, reducing the orchestration of state management to a minimum. Making you a **happier** and more **productive** developer!
Develop the application state, effects and actions without leaving [VS Code](https://code.visualstudio.com/), or use the standalone development tool. Everything that happens in your app is tracked and you can seamlessly code and run logic to verify that everything works as expected without necessarily having to implement UI.
Copy file name to clipboardExpand all lines: core/defining-state.md
+6-13Lines changed: 6 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -113,10 +113,6 @@ export const state = {
113
113
{% endtab %}
114
114
{% endtabs %}
115
115
116
-
{% hint style="warning" %}
117
-
It is import that you do **NOT** use arrow functions on your methods. The reason is that this binds the context of the method to the instance itself, meaning that Overmind is unable to proxy access and allow you to do tracked mutations
118
-
{% endhint %}
119
-
120
116
You can now use this instance as normal and of course create new ones.
There are two important rules for predictable transitions:
420
-
421
-
1. The transition should always be **returned**
422
-
2. Only **synchronous** transitions can mutate the state
414
+
{% hint style="info" %}
415
+
If your transition runs asynchronously you should return the transition to ensure that the action execution is tracked
423
416
{% endhint %}
424
417
425
418
What is important to realize here is that our logic is separated into **allowable** transitions. That means when we are waiting for the user on **line 4** and some other logic has changed the state to **unauthenticated** in the meantime, the user will not be set, as the **authenticated** transition is now not possible. This is what state machines do. They group logic into states that are allowed to run, preventing invalid logic to run.
Typically you explicitly communicate with effects from actions, by calling methods. But sometimes you need effects to know about the state of the application, or maybe some internal state in the effect should be exposed on your application state. Again we can take advantage of an **initialize** method on the effect:
Copy file name to clipboardExpand all lines: faq.md
-4Lines changed: 0 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,9 +8,5 @@ First… try to refresh your app to reconnect. If this does not work make sure t
8
8
9
9
Restart VS Code
10
10
11
-
## My operator actions are not running?
12
-
13
-
Operators are identified with a Symbol. If you happen to use Overmind across packages you might be running two versions of Overmind. The same goes for core package and view package installed out of version sync. Make sure you are only running on package of Overmind by looking into your **node\_modules** folder.
Copy file name to clipboardExpand all lines: features/testing.md
+29-11Lines changed: 29 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,18 +11,22 @@ You can also do **unit testing** of actions and effects. This will cover expecte
11
11
When you write tests you will create many instances of a mocked version of Overmind with the configuration you have created. To ensure that this configuration can be used many times we have to separate our configuration from the instantiation of the actual app.
12
12
13
13
{% tabs %}
14
-
{% tab title="overmind/index.js" %}
14
+
{% tab title="overmind/index.ts" %}
15
15
```typescript
16
16
import { IConfig } from'overmind'
17
17
import { state } from'./state'
18
18
19
19
exportconst config = {
20
20
state
21
21
}
22
+
23
+
declaremodule'overmind' {
24
+
interfaceConfigextendsIConfig<typeofconfig> {}
25
+
}
22
26
```
23
27
{% endtab %}
24
28
25
-
{% tab title="index.js" %}
29
+
{% tab title="index.ts" %}
26
30
```typescript
27
31
import { createOvermind } from'overmind'
28
32
import { config } from'./overmind'
@@ -39,9 +43,11 @@ Now we are free to import our configuration without touching the application ins
39
43
When testing an action you’ll want to verify that changes to state are performed as expected. To give you the best possible testing experience Overmind comes with a mocking tool called **createOvermindMock**. It takes your application configuration and allows you to run actions as if they were run from components.
40
44
41
45
{% tabs %}
42
-
{% tab title="overmind/actions.js" %}
46
+
{% tab title="overmind/actions.ts" %}
43
47
```typescript
44
-
exportconst getPost =async ({ state, api }, id) {
48
+
import { AsyncAction } from'overmind'
49
+
50
+
exportconst getPost:AsyncAction<string> =async ({ state, api }, id) {
You might want to test if a thrown error is handled correctly here. This is an example of how you could do that:
58
64
59
65
{% tabs %}
60
-
{% tab title="overmind/actions.test.js" %}
66
+
{% tab title="overmind/actions.test.ts" %}
61
67
```typescript
62
68
import { createOvermindMock } from'overmind'
63
69
import { config } from'./'
@@ -108,7 +114,7 @@ If your actions can result in multiple scenarios a unit test is beneficial. But
108
114
You do not have to explicitly write the expected state. You can also use for example [JEST](https://www.overmindjs.org/guides/intermediate/05_writingtests?view=react&typescript=true) for snapshot testing. The mock instance has a list of mutations performed. This is perfect for snapshot testing.
109
115
110
116
{% tabs %}
111
-
{% tab title="overmind/actions.test.js" %}
117
+
{% tab title="overmind/actions.test.ts" %}
112
118
```typescript
113
119
import { createOvermindMock } from'overmind'
114
120
import { config } from'./'
@@ -156,7 +162,7 @@ In this scenario we would also ensure that the **isLoadingPost** state indeed fl
156
162
The **onInitialize** hook will not trigger during testing. To test this action you have to trigger it yourself.
157
163
158
164
{% tabs %}
159
-
{% tab title="overmind/onInitialize.test.js" %}
165
+
{% tab title="overmind/onInitialize.test.ts" %}
160
166
```typescript
161
167
import { createOvermindMock } from'overmind'
162
168
import { config } from'./'
@@ -191,17 +197,29 @@ A simple example of this is doing requests. Maybe you want to use e.g. [AXIOS](h
191
197
This is just an example showing you how you can structure your code for optimal testability. You might prefer a different approach or maybe rely on integration tests for this. No worries, you do what makes most sense for your application:
192
198
193
199
{% tabs %}
194
-
{% tab title="overmind/effects.js" %}
200
+
{% tab title="overmind/effects.ts" %}
195
201
```typescript
196
202
import*asaxiosfrom'axios'
203
+
import { Post } from'./state'
204
+
205
+
interfaceIRequest {
206
+
get<T>(url:string):Promise<T>
207
+
}
208
+
209
+
interfaceIOptions {
210
+
authToken:string
211
+
baseUrl:string
212
+
}
197
213
198
214
// This is the class we can create new instances of when testing
Copy file name to clipboardExpand all lines: guides-1/server-side-rendering.md
+1-53Lines changed: 1 addition & 53 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -36,7 +36,7 @@ Here we only export the configuration from the main Overmind file. The instantia
36
36
37
37
## Preparing effects
38
38
39
-
The effects will also be shared with the server. Typically this is not an issue, but you should be careful about creating effects that run logic when they are defined. You might also consider lazy-loading effects so that you avoid loading them on the server at all. You can read more about them in [EFFECTS](running-side-effects.md).
39
+
The effects will also be shared with the server. Typically this is not an issue, but you should be careful about creating effects that run logic when they are defined. You might also consider lazy-loading effects so that you avoid loading them on the server at all. You can read more about them in [EFFECTS](../core/running-side-effects.md).
If you are using state first routing, make sure you prevent the router from firing off the initial route, as this is not needed.
104
104
{% endhint %}
105
105
106
-
## OnInitialize
107
-
108
-
The `onInitialized` action does not run on the server. The reason is that it is considered a side effect you might not want to run, so we do not force it. If you do want to run an action as Overmind fires up both on the client and the server you can rather create a custom action for it.
109
-
110
-
{% tabs %}
111
-
{% tab title="overmind/actions.js" %}
112
-
```javascript
113
-
exportconstinitialize= () => {
114
-
// Whatever...
115
-
}
116
-
```
117
-
{% endtab %}
118
-
119
-
{% tab title="client/index.js" %}
120
-
```typescript
121
-
import { createOvermind } from'overmind'
122
-
import { config } from'./overmind'
123
-
124
-
const overmind =createOvermind(config)
125
-
overmind.actions.initialize()
126
-
```
127
-
{% endtab %}
128
-
129
-
{% tab title="server/index.js" %}
130
-
```javascript
131
-
import { createOvermindSSR } from'overmind'
132
-
import { config } from'../client/overmind'
133
-
134
-
exportdefaultasync (req, res) => {
135
-
constovermind=createOvermindSSR(config)
136
-
awaitovermind.actions.initialize()
137
-
138
-
consthtml=renderToString(
139
-
// Whatever implementation your view layer provides
Copy file name to clipboardExpand all lines: introduction.md
+5-9Lines changed: 5 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,11 +8,7 @@ If you rather want to go right ahead and set up a local project, please have a l
8
8
9
9
Before we move on, have a quick look at this sandbox. It is a simple counter application and it gives you some foundation before talking more about Overmind and building applications.
We have now separated out the Overmind related logic into its own file, **app.js**. This file creates the Overmind instance and also exports how the components will interact with the state and the actions, the hook called **useApp**. Vue and Angular has other mechanisms conventional to those frameworks where application state and actions can be accessed.
103
99
@@ -187,7 +183,7 @@ Any function you insert into the state tree is treated as derived state. That me
187
183
188
184
Now let us move into an even more complex application. Here we have added **effects**. Specifically effects to handle routing, storing todos to local storage and producing unique ids for the todos. We have added an **onInitialize** hook which is a special function Overmind runs when the application starts.
You can think of effects as a contract between your application and the outside world. You write an effect API of **what** your application needs and some 3rd party tool or native JavaScript API will implement **how** to provide it. Let us look at the router:
193
189
@@ -227,7 +223,7 @@ This argument passed is transformed into something Page can understand. What thi
227
223
228
224
Defining all the state, actions and effects on one object would not work very well for a large application. A convention in Overmind is to split these concepts into different files behind folders representing a domain of the application. In this next sandbox you can see how we split up state, actions and effects into different files. They are all exposed through a main file representing that domain, in this case “the root domain”:
Also notice that we have split up the instantiation of Overmind from the definition of the application. What this allows us to do is reuse the same application configuration for testing purposes and/or server side rendering. We separate the definition from the instantiation.
233
229
@@ -243,7 +239,7 @@ Have a look at this new project where we have typed the application:
243
239
You have to **OPEN IN EDITOR** to get the full Typescript experience.
As you can see we only have to add an **Action** type to our functions and optionally give it an input type. This is enough for the action to give you all information about the application. Try changing some code and even add some code to see how Typescript helps you to explore the application and ensure that you implement new functionality correctly.
0 commit comments