Skip to content

Commit e203aa1

Browse files
docs(website): docs updates
1 parent ef3f40b commit e203aa1

File tree

6 files changed

+105
-4
lines changed

6 files changed

+105
-4
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export default () => [
2+
{
3+
code: `
4+
const posts = state.userPosts(userId)
5+
`,
6+
},
7+
]
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
export default (ts) =>
2+
ts
3+
? [
4+
{
5+
fileName: 'overmind/operators.ts',
6+
code: `
7+
import { Operator, map } from 'overmind'
8+
9+
export const getTargetValue: Operator<Event, string> = map(({ value : event }) =>
10+
event.currentTarget.value
11+
)
12+
`,
13+
},
14+
{
15+
fileName: 'overmind/actions.ts',
16+
code: `
17+
import { Operator, pipe, action } from 'overmind'
18+
import { getTargetValue } from './operators'
19+
20+
export const setValue: Operator<Event, string> = pipe(
21+
getTargetValue,
22+
action(({ state, value }) => {
23+
state.value = value
24+
})
25+
)
26+
`,
27+
},
28+
]
29+
: [
30+
{
31+
fileName: 'overmind/operators.js',
32+
code: `
33+
import { map } from 'overmind'
34+
35+
export const getTargetValue = map(({ value : event }) =>
36+
event.currentTarget.value
37+
)
38+
`,
39+
},
40+
{
41+
fileName: 'overmind/actions.js',
42+
code: `
43+
import { pipe, action } from 'overmind'
44+
import { getTargetValue } from './operators'
45+
46+
export const setValue = pipe(
47+
getTargetValue,
48+
action(({ state, value }) => {
49+
state.value = value
50+
})
51+
)
52+
`,
53+
},
54+
]

packages/overmind-website/guides/beginner/02_definingstate.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,22 @@ That means the function only runs when accessed and the depending state has chan
6767
h(Notice, null, "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")
6868
```
6969

70+
You might intuitively want to pass in an argument to this derived function, but that is actually a very problematic concept that can be solved more elegantly. An example of this would be that you open a page showing the current user and with the **id** of that user you want find the related posts. So you might want to:
71+
72+
73+
```marksy
74+
h(Example, { name: "guide/definingstate/derived_passvalue" })
75+
```
76+
77+
But this is actually a really bad idea and there are a couple of reasons for that:
78+
79+
1. We need a mechanism to use the argument passed in as a caching key. With an **id** that is not so difficult, but what if you passed in an object with some options? Or maybe you use the same object multiple times, but the values on the object changed? Should we stringify the object? What about multiple arguments? As you can understand it becomes quite complex
80+
2. When should we remove a cached value? We have no idea when you have stopped using the derived value, so we do not know when to remove it. We could have created a limited cache, though how big should it be? 10 entries? What if you have a list of 100 users? Should it be configurable?
81+
82+
So to solve this specific scenario you would rather create a new state called **currentUserId** and use that state to derive the posts. So whenever you have an itch to pass in a value to a derived, try imagine it from the perspective of only using state instead. This also improves the debugging experience.
83+
84+
Also remember that **derived** is a concept for computation heavy derived state, you most commonly want to use a **getter**.
85+
7086
## Getter
7187

7288
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. This is similar to deriving state, though they are dynamic. That means derived state can only be defined once and needs to stay in the state tree. A getter is just like a plain value, it can be added an removed at any point. Getters does **not** cache the result for that very reason, but whatever state they access is tracked.
@@ -84,6 +100,10 @@ We define the state of the application in **state** files. For example, the top
84100
h(Example, { name: "guide/definingstate/define" })
85101
```
86102

103+
```marksy
104+
h(TypescriptNotice, null, "Is is important that you define your state with a **type**, do **NOT** use an **interface**")
105+
```
106+
87107
As your application grows you will most likely move parts of the state to their own namespaces. An example of that could be:
88108

89109
```marksy

packages/overmind-website/guides/beginner/03_connectingcomponents.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ All the actions defined in the Overmind application is available to connected co
6565
h(Example, { name: "guide/connectingcomponents/actions" })
6666
```
6767

68+
```marksy
69+
h(Notice, null, "If you need to pass multiple values to an action, you rather use an **object** instead")
70+
```
71+
6872
## Reactions
6973

7074
Sometimes you want to make something happen inside a component related to a state change. This is typically doing some manual work on the DOM. When you connect a component to overmind it also gets access to **addMutationListener**. This function allows you to subscribe to changes in state, mutations as we call them. Each mutation holds information about what kind of mutation it was, at what path it happened and even any arguments used in the mutation. You can use all this information to create an effect.

packages/overmind-website/guides/intermediate/03_typescript.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
# Typescript
22

3-
Overmind is written in Typescript and it is written with a focus on your keeping as little time as possible helping Typescript understand what your app is all about. Typescript will spend a lot more time helping you. There are actually two approaches to typing in Overmind.
3+
Overmind is written in Typescript and it is written with a focus on your keeping as little time as possible helping Typescript understand what your app is all about. Typescript will spend a lot more time helping you.
44

5-
## Declare module
5+
## Two typing approaches
6+
7+
### 1. Declare module
68

79
The most straight forward way to type your application is to use the **declare module** approach. This will work for most applications, but might make you feel uncomfortable as a harcore Typescripter. The reason is that we are overriding an internal type, meaning that you can only have one instance of Overmind running inside your application.
810

@@ -16,7 +18,7 @@ Now you can import any type directly from Overmind and it will understand the co
1618
h(Example, { name: "guide/typescript/declare_imports.ts" })
1719
```
1820

19-
## Explicit typing
21+
### 2. Explicit typing
2022
You can also explicitly type your application. This gives more flexibility.
2123

2224
```marksy
@@ -35,6 +37,9 @@ h(Example, { name: "guide/typescript/explicit_import.ts" })
3537
h(Notice, null, "The Overmind documentation is written for implicit typing. That means whenever you see a type import directly from the Overmind package, you should rather import from your own defined types")
3638
```
3739

40+
## Linting
41+
42+
When you are using TSLint it is important that you use the official [Microsoft Extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-typescript-tslint-plugin) for VS Code.
3843

3944
## Actions
4045

packages/overmind-website/guides/intermediate/04_goingfunctional.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ Here we see the **parallel** operator being used as a callable action to run two
4444

4545
## Piping
4646

47-
4847
To compose the different operators together you typically use **pipe**. You can also compose pipes into pipes, it is just an operator like the rest.
4948

5049
```marksy
@@ -53,6 +52,18 @@ h(Example, { name: "guide/goingfunctional/pipe" })
5352

5453
There are several operators available and you can quite easily create new operators from scratch. They are built with the [op-op spec](https://github.com/christianalfoni/op-op-spec). A specification designed specifically to move state management solutions into a functional world.
5554

55+
## Inputs and Outputs
56+
57+
To produce new values throughout your pipe you can use the **map** operator. It will put whatever value you return from it on the pipe for the next operator to consume.
58+
59+
```marksy
60+
h(Example, { name: "guide/goingfunctional/map" })
61+
```
62+
63+
```marksy
64+
h(TypescriptNotice, null, "Notice here that we are typing both the input and the output. Both for the **map** operator and the **pipe** operator. This is important to manage the composition of operators. Typically operators pass on the same value they receive, meaning that you do not need the second typing parameter for the **Operator** type.")
65+
```
66+
5667
## Factories
5768

5869
A familiar concept in functional programming is the use of factories. A factory is a function that creates an operator. This can be used to send *options* to an operator. A typical example of this is the **lengthGreaterThan** operator we built previously.

0 commit comments

Comments
 (0)