Skip to content

Commit 9b1ef1d

Browse files
Christian AlfoniChristian Alfoni
authored andcommitted
docs(website): improve introduction
1 parent 0815652 commit 9b1ef1d

File tree

1 file changed

+26
-22
lines changed

1 file changed

+26
-22
lines changed

packages/overmind-website/src/components/Introduction/introduction.md

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Welcome to Overmind
22

3-
In this introduction you will get an overview of Overmind and how you can think about application development. We will be using [React](https://reactjs.org/) to write the UI, but you can use also use Overmind with [Vue](https://vuejs.org/) and [Angular](https://angular.io).
3+
In this introduction you will get an overview of Overmind and how you can think about application development. We will be using [React](https://reactjs.org/) to write the UI, but you can use Overmind with [Vue](https://vuejs.org/) and [Angular](https://angular.io) if either of those is your preference.
44

55
```marksy
66
h(Notice, null, "If you rather want to go right ahead and set up a local project, please have a look at the [quickstart](/guides/beginner/01_quickstart) guide.")
@@ -21,20 +21,20 @@ First of all we have to talk about **application** and **component** state. In t
2121

2222
If the count example above was the entire application it would not make any sense to introduce application state and Overmind. But if you were to increase the scope of this simple application you would be surprised how quickly you get into the following scenarios:
2323

24-
1. **You want to introduce an other component that needs to know about the current state of the count.** This new component can not be a parent of the component owning the count state. It can not be a sibling either. It has to be a child. If it is not an immediate child the count state has to be passed down the componen tree until it reaches your new component.
24+
1. **You want to introduce an other component that needs to know about the current state of the count.** This new component can not be a parent of the component owning the count state. It can not be a sibling either. It has to be a child. If it is not an immediate child the count state has to be passed down the component tree until it reaches your new component.
2525
2. **You want to remember the count, even though it is not shown in the UI**. Your count is behind one of multiple tabs in the UI. When the user changes the tabs you do not want the count to reset. The only way to ensure this is to move the count state up to a parent component that is no longer a child of the tab and then pass the count state back down again.
26-
3. **You want to change the count from a side effect**. You have a websocket connection which changes the count when a message is received. If you want to avoid this websocket connection to open and close as the component mounts and unmounts you will have to move the websocket connection and count state up the component tree.
27-
4. **You want to change the count as part of a flow**. When you click the increase count button you need to change both the count state and an other state related to a different part of the UI. To able able to change both states at the same time they have to live inside the same component, which has to be a parent of both components using the state.
26+
3. **You want to change the count from a side effect**. You have a websocket connection which changes the count when a message is received. If you want to avoid this websocket connection to open and close as the component mounts and unmounts you will have to move the websocket connection up the component tree.
27+
4. **You want to change the count as part of a flow**. When you click the increase count button you need to change both the count state and an other state related to a different part of the UI. To be able to change both states at the same time, they have to live inside the same component, which has to be a parent of both components using the state.
2828

29-
Introducing these scenarios we said: **You want**. In reality we rarely know exactly what we want. We do not know how our state and components will evolve. And this is the most important point. By using application state instead of component state you get flexibility to manage whatever comes down the road.
29+
Introducing these scenarios we said: **You want**. In reality we rarely know exactly what we want. We do not know how our state and components will evolve. And this is the most important point. By using application state instead of component state you get flexibility to manage whatever comes down the road without having to refactor wrong assumptions.
3030

31-
**So is component state bad?**. No, certainly not. You do not want to overload your application state with state that could just as well have been component state. The tricky thing is to figure out when that is absolutely the case. For example:
31+
**So is component state bad?** No, certainly not. You do not want to overload your application state with state that could just as well have been component state. The tricky thing is to figure out when that is absolutely the case. For example:
3232

33-
1. **Modals should certainly be component state?**. Not all modals are triggered by a user interaction. A profile modal might be triggered by clicking a profile picture, but also open up when a user opens the application and is missing information.
34-
2. **The active tab should certainly be component state?**. The active tab might be part of the url query, `/user?tab=count`. That means it should rather be a hyperlink where your application handles the routing and provides state to identify the active tab.
35-
3. **Inputs should certainly be component state?**. If the input is part of an application wide flow, you might want to empty out the content of that input, or even change it to something else.
33+
1. **Modals should certainly be component state?** Not all modals are triggered by a user interaction. A profile modal might be triggered by clicking a profile picture, but also open up when a user opens the application and is missing information.
34+
2. **The active tab should certainly be component state?** The active tab might be part of the url query, `/user?tab=count`. That means it should rather be a hyperlink where your application handles the routing and provides state to identify the active tab.
35+
3. **Inputs should certainly be component state?** If the input is part of an application flow, you might want to empty out the content of that input, or even change it to something else.
3636

37-
How you want to go about this is totally up to you. We are not telling you exactly how to separate application and component state. What we can say though; **"If you lean towards application state your are more flexible to future changes"**.
37+
How you want to go about this is totally up to you. We are not telling you exactly how to separate application and component state. What we can tell you though; **"If you lean towards application state your are more flexible to future changes"**.
3838

3939
## Defining state
4040

@@ -51,7 +51,7 @@ createOvermind({
5151

5252
This state object will hold all the application state, we call it a *single state tree*. That does not mean you define all the state in one file and we will talk more about that later. For now lets talk about what you put into this state tree.
5353

54-
A single state tree favours serializable state. That means state that can be `JSON.parse` and `JSON.stringify` back and forth. Which means it can be safely passed between the client and the server, localStorage or to web workers. That means you will use **strings**, **numbers**, **booleans**, **arrays**, **objects** and **null**. Overmind does not prevent you from using other complex objects, but it is encouraged to use these core data types.
54+
A single state tree favours serializable state. That means state that can be `JSON.parse` and `JSON.stringify` back and forth. It can be safely passed between the client and the server, localStorage or to web workers. You will use **strings**, **numbers**, **booleans**, **arrays**, **objects** and **null**. Overmind does not prevent you from using other complex objects, but it is encouraged to use these core data types.
5555

5656
## Defining actions
5757

@@ -105,7 +105,7 @@ h(Sandbox, {
105105
})
106106
```
107107

108-
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.
108+
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.
109109

110110
## References
111111

@@ -149,7 +149,7 @@ state.todos[myReference]
149149
delete state.todos[myReference]
150150
```
151151

152-
Using references also ensures that only one instance of any todo will live in your state tree. The todo itself lives on the **todos** object, while everything else in the state tree references a todo by using its id. For example our **editingTodoId** state uses the id of a todo to reference which todo is currently being edited.
152+
Using references also ensures that only one instance of any todo will live in your state tree. The todo itself lives on the **todos** state, while everything else in the state tree references a todo by using its id. For example our **editingTodoId** state uses the id of a todo to reference which todo is currently being edited.
153153

154154
## Deriving state
155155

@@ -185,7 +185,7 @@ createOvermind({
185185
})
186186
```
187187

188-
Our state tree is concerned with state values that you will change using actions. But you can also automatically produce state values based on existing state. An example of this would be to list the **currentTodos**. It uses the todos and filter state to figure out what todos to actually display. Sometimes this is called computed values.
188+
Our state tree is concerned with state values that you will change using actions. But you can also automatically produce state values based on existing state. An example of this would be to list the **currentTodos**. It uses the todos and filter state to figure out what todos to actually display. Sometimes this is called computed state. We call it **derived** state.
189189

190190
Any function you insert into the state tree is treated as derived state. That means these functions receives a preset first argument which is the immediate state, the state object the derived is attached to. In bigger applications you might also need to use the second argument, which is the root state of the application. It will automatically track whatever state you use and then flag itself as dirty whenever it changes. If derived state is used while being dirty, the function will run again. If it is not dirty a cached value is returned.
191191

@@ -200,7 +200,7 @@ h(Sandbox, {
200200
})
201201
```
202202

203-
You can think of effects as a contract between your application and the outside world. You write an 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:
203+
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:
204204

205205
```ts
206206
createOvermind({
@@ -222,7 +222,7 @@ createOvermind({
222222
})
223223
```
224224

225-
The router uses the [Page](https://www.npmjs.com/package/page) tool to manage routing. It takes a "url to action" option that makes sense for this application, but you could define this however you wanted:
225+
The router uses the [Page](https://www.npmjs.com/package/page) tool to manage routing. It takes a "url to action" option that makes sense for this application, but you could define this however you wanted.
226226

227227
```ts
228228
effects.router.initialize({
@@ -232,7 +232,7 @@ effects.router.initialize({
232232
});
233233
```
234234

235-
This option is transformed into something Page can understand. What this means is that we can easily switch out Page with some other tool later if we wanted to, or maybe if you app ran in different environments you could change out the implementation of the router dynamically. We were also able to combine **page** and **page.start** behind one method, which cleans up our application code. We did the same for the **storage** effect. We use localStorage and JSON.parse/JSON.stringify behind a single method.
235+
This argument passed is transformed into something Page can understand. What this means is that we can easily switch out Page with some other tool later if we wanted to, or maybe if the app ran in different environments you could change out the implementation of the router dynamically. We were also able to combine **page** and **page.start** behind one method, which cleans up our application code. We did the same for the **storage** effect. We use localStorage and JSON.parse/JSON.stringify behind a single method.
236236

237237
## Scaling up the application
238238

@@ -294,7 +294,7 @@ To learn more about Overmind and Typescript read the [Typescript](/guides/beginn
294294
295295
## Development tool
296296
297-
Overmind also ships with its own development tool. It can be installed as a [VSCode plugin](https://marketplace.visualstudio.com/items?itemName=christianalfoni.overmind-devtools-vscode) or installed as an NPM package. The development tool knows everything about what is happening inside the application. It shows you all the state, running actions and connected components. By default Overmind connects automatically to the development if it is running. Try now by going to the **index.tsx** file and change:
297+
Overmind also ships with its own development tool. It can be installed as a [VSCode plugin](https://marketplace.visualstudio.com/items?itemName=christianalfoni.overmind-devtools-vscode) or installed as an NPM package. The development tool knows everything about what is happening inside the application. It shows you all the state, running actions and connected components. By default Overmind connects automatically to the devtool if it is running. Try now by going to the **index.tsx** file and change:
298298
299299
```ts
300300
export const overmind = createOvermind(config, {
@@ -310,13 +310,13 @@ export const overmind = createOvermind(config, {
310310
});
311311
```
312312

313-
Now go to your terminal and use the NPM executor to instantly fire up the development tool:
313+
Go to your terminal and use the NPM executor to instantly fire up the development tool.
314314

315315
```
316316
npx overmind-devtools
317317
```
318318

319-
Refresh the sandbox preview and you should now see the devtools populated with information from the application.
319+
Refresh the sandbox preview and you should see the devtools populated with information from the application.
320320

321321
```marksy
322322
h(Notice, null, "This only works in **CHROME** when running on codesandbox.io, due to domain security restrictions. It works on all browsers when running your project locally.")
@@ -328,7 +328,11 @@ Here we get an overview of the current state of the application, including our d
328328

329329
![TodoMvc Actions](/images/todomvc_actions.png)
330330

331-
Here we can see that we grabbing todos from local storage and initializing our router. We can also see that the router instantly fires off our **changeFilter** action causing a state change on the filter. At the end we can see that our reaction triggered, saving the todos as we did update that state during the execution of this action.
331+
Here we can see that we grabbing todos from local storage and initializing our router. We can also see that the router instantly fires off our **changeFilter** action causing a state change on the filter. At the end we can see that our reaction triggered, saving the todos.
332+
333+
```marksy
334+
h(Notice, null, "You might wonder why the reaction triggered when it was defined after we changed the **todos** state. Overmind batches up changes to state and *flushes* at optimal points in the execution. For example when an action ends or some asynchronous code starts running. The reaction reacts to these flushes, just like components do.")
335+
```
332336

333337
Moving on we also get insight into components looking at our application state:
334338

@@ -350,6 +354,6 @@ Our todo has been added and we can even see how the derived state was affected b
350354

351355
## Moving from here
352356

353-
I hope this introduction got you excited about developing applications and working with Overmind. From this point you can continue working with [codesandbox.io](https://codesandbox.io) or set up a local development flow. It is highly encouraged to use Overmind with Typescript, it does not get any more complex than what you see in this simple TodoMvc application.
357+
We hope this introduction got you excited about developing applications and working with Overmind. From this point you can continue working with [codesandbox.io](https://codesandbox.io) or set up a local development flow. It is highly encouraged to use Overmind with Typescript, it does not get any more complex than what you see in this simple TodoMvc application.
354358

355359
Move over to the [quickstart](/guides/beginner/01_quickstart) to get help setting up your project. The other guides will give you a deeper understanding of how Overmind works. If you are lost please talk to us on [discord](https://discord.gg/YKw9Kd) and we are happy to help. And yeah... have fun! :-)

0 commit comments

Comments
 (0)