Skip to content

Commit 7c7267d

Browse files
christianalfonigitbook-bot
authored andcommitted
GitBook: [master] one page modified
1 parent 5de1319 commit 7c7267d

File tree

1 file changed

+179
-0
lines changed

1 file changed

+179
-0
lines changed

namespacing.md

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,181 @@
11
# Namespacing
22

3+
When your application grows it can be a good idea to separate your state and logic into different domains by using namespaces. An example of this is when you have an application with different pages. You might want to use each page as a namespace for state and logic. It might also make sense to have a namespace responsible for managing the data of your application, talking to the server etc. There is no one right answer here and it is up to you to define these namespaces.
4+
5+
Instead of defining one application module exporting state, providers and actions, you can define multiple modules.
6+
7+
{% code-tabs %}
8+
{% code-tabs-item title="app/modules/moduleA.js" %}
9+
```javascript
10+
export const state = {
11+
title: 'Page A'
12+
}
13+
14+
export const actions = action => ({
15+
doThis: action()
16+
})
17+
```
18+
{% endcode-tabs-item %}
19+
20+
{% code-tabs-item title="app/modules/moduleB.js" %}
21+
```javascript
22+
export const state = {
23+
title: 'Page B'
24+
}
25+
26+
export const actions = action => ({
27+
doThis: action()
28+
})
29+
```
30+
{% endcode-tabs-item %}
31+
32+
{% code-tabs-item title="app/modules/moduleA.ts" %}
33+
```typescript
34+
import { Action } from '../'
35+
36+
type State = {
37+
title: string
38+
}
39+
40+
export const state: State = {
41+
title: 'Page A'
42+
}
43+
44+
export const actions = (action: Action) => ({
45+
doThis: action()
46+
})
47+
48+
```
49+
{% endcode-tabs-item %}
50+
51+
{% code-tabs-item title="app/modules/moduleB.ts" %}
52+
```typescript
53+
import { Action } from '../'
54+
55+
type State = {
56+
title: string
57+
}
58+
59+
export const state: State = {
60+
title: 'Page B'
61+
}
62+
63+
export const actions = (action: Action) => ({
64+
doThis: action()
65+
})
66+
```
67+
{% endcode-tabs-item %}
68+
{% endcode-tabs %}
69+
70+
In the main application file you will now use the **namespaces** function to define the namespaces:
71+
72+
{% code-tabs %}
73+
{% code-tabs-item title="app/index.js" %}
74+
```javascript
75+
import App, { namespaces } from 'overmind/$VIEW'
76+
import * as moduleA from './modules/moduleA'
77+
import * as moduleB from './modules/moduleB'
78+
79+
const config = namespaces({
80+
moduleA,
81+
moduleB
82+
})
83+
84+
const app = new App(config)
85+
86+
export const connect = app.connect
87+
```
88+
{% endcode-tabs-item %}
89+
90+
{% code-tabs-item title="app/index.ts" %}
91+
```typescript
92+
import App, { TConnect, TContext, IAction, namespaces } from 'overmind/$VIEW'
93+
import * as moduleA from './modules/moduleA'
94+
import * as moduleB from './modules/moduleB'
95+
96+
const config = namespaces({
97+
moduleA,
98+
moduleB
99+
})
100+
101+
export type Context = TContext<typeof config.state, typeof config.providers>
102+
103+
export type Action = IAction<typeof config.state, Context>
104+
105+
const app = new App(config)
106+
107+
export type Connect = TConnect<typeof app.state, typeof app.actions>
108+
109+
export const connect = app.connect
110+
```
111+
{% endcode-tabs-item %}
112+
{% endcode-tabs %}
113+
114+
Now your state, providers and actions are namespaced accordingly. Meaning that inside actions you would need to use `state.moduleA.title`and `state.moduleB.title`, the same goes for providers and actions.
115+
116+
### Dynamic namespaces
117+
118+
If you want to create a module that is shared between projects you want to make sure that any namespace might be used, but still be able to point correctly to state and providers inside the actions of your shared module.
119+
120+
A module can also be defined as a function which receives the namespace:
121+
122+
{% code-tabs %}
123+
{% code-tabs-item title="app/index.js" %}
124+
```javascript
125+
export default (namespace) => ({
126+
state: {
127+
foo: 'bar'
128+
},
129+
actions: action => ({
130+
doThis: action()
131+
.map((_, context) => context[namespace].hello())
132+
.mutation(state => state[namespace].foo = 'bar2')
133+
}),
134+
providers: {
135+
hello: () => 'hello'
136+
}
137+
})
138+
```
139+
{% endcode-tabs-item %}
140+
141+
{% code-tabs-item title="app/index.ts" %}
142+
```typescript
143+
import { Namespace, IAction, TContext } from 'overmind'
144+
145+
export default (namespace: Namespace) => {
146+
type State = {
147+
foo: string
148+
}
149+
type NamespacedState = {
150+
[namespace]: State
151+
}
152+
type NamespacedProviders = {
153+
[namespace]: typeof providers
154+
}
155+
type Context = TContext<NamespacedState, NamespacedProviders>
156+
type Action = IAction<NamespacedState, Context>
157+
158+
const state: State = {
159+
foo: 'bar'
160+
}
161+
const providers = {
162+
hello: () => 'hello'
163+
}
164+
const actions = (action: Action) => ({
165+
doThis: action()
166+
.map((_, context) => context[namespace].hello())
167+
.mutation(state => state[namespace].foo = 'bar2')
168+
})
169+
170+
return {
171+
state,
172+
actions,
173+
providers
174+
}
175+
}
176+
```
177+
{% endcode-tabs-item %}
178+
{% endcode-tabs %}
179+
180+
As you can see we are actively using the passed in namespace inside the actions to look up correct state and providers.
181+

0 commit comments

Comments
 (0)