|
@@ -3,14 +3,12 @@ id: third-party-mobx
|
3
|
3
|
title: MobX
|
4
|
4
|
sidebar_label: MobX
|
5
|
5
|
---
|
|
6
|
+import useBaseUrl from '@docusaurus/useBaseUrl';
|
6
|
7
|
|
7
|
|
-## MobX
|
8
|
8
|
MobX is one of the most popular state management libraries used by applications sized from small to large.
|
9
|
9
|
With the introduction of the new React Context API, MobX can now be very easily integrated in React Native Navigation
|
10
|
10
|
projects.
|
11
|
11
|
|
12
|
|
-In the example we will be creating a small Counter app.
|
13
|
|
-
|
14
|
12
|
:::info Note
|
15
|
13
|
With the introduction of the new Context API, there is no need to use `Provider` pattern with MobX and you
|
16
|
14
|
can now just use the React Context API.
|
|
@@ -18,25 +16,32 @@ can now just use the React Context API.
|
18
|
16
|
Also the example uses `mobx-react-lite` but you can use the normal `mobx-react`.
|
19
|
17
|
:::
|
20
|
18
|
|
21
|
|
-## Create a Counter store.
|
22
|
|
-Let's first create a counter store using MobX.
|
|
19
|
+## Sharing a store between multiple screens
|
|
20
|
+
|
|
21
|
+In the example bellow we will be creating a small Counter app. We will learn how to integrate Mobx with React-Native-Navigation and demonstrate how updating the store from one component, triggers renders in other components connected to the same store.
|
|
22
|
+
|
|
23
|
+Once you finish implementing the example, your screen should look similar to this:
|
|
24
|
+<img width="30%" src={useBaseUrl('/img/mobx_counter.png')} />
|
|
25
|
+
|
|
26
|
+### Step 1 - Create a Counter store
|
|
27
|
+Let's first create a counter store using MobX. Our store has a single `count` object and two methods to increment and decrement it.
|
23
|
28
|
|
24
|
29
|
```tsx
|
25
|
30
|
// counter.store.js
|
26
|
|
-import React from 'react'
|
27
|
|
-import { observable, action } from 'mobx'
|
|
31
|
+import React from 'react';
|
|
32
|
+import { observable, action } from 'mobx';
|
28
|
33
|
|
29
|
34
|
class CounterStore {
|
30
|
|
- @observable count = 0
|
|
35
|
+ @observable count = 0;
|
31
|
36
|
|
32
|
37
|
@action.bound
|
33
|
38
|
increment() {
|
34
|
|
- this.count += 1
|
|
39
|
+ this.count += 1;
|
35
|
40
|
}
|
36
|
41
|
|
37
|
42
|
@action.bound
|
38
|
43
|
decrement() {
|
39
|
|
- this.count -= 1
|
|
44
|
+ this.count -= 1;
|
40
|
45
|
}
|
41
|
46
|
}
|
42
|
47
|
|
|
@@ -46,27 +51,29 @@ const counterStore = new CounterStore()
|
46
|
51
|
export const CounterStoreContext = React.createContext(counterStore)
|
47
|
52
|
```
|
48
|
53
|
|
49
|
|
-## Consuming the store
|
|
54
|
+### Step 2 - Consuming the store
|
50
|
55
|
You can consume the Counter store in any React components using `React.useContext`.
|
51
|
56
|
|
52
|
57
|
```tsx
|
53
|
|
-// Counter.js
|
54
|
|
-import React from 'react'
|
55
|
|
-import { Button, Text, View } from 'react-native'
|
56
|
|
-import { observer } from 'mobx-react-lite'
|
57
|
|
-import { CounterStoreContext } from './counter.store'
|
|
58
|
+// CounterScreen.js
|
|
59
|
+import React from 'react';
|
|
60
|
+import { Button, Text, View } from 'react-native';
|
|
61
|
+import { observer } from 'mobx-react-lite';
|
|
62
|
+import { CounterStoreContext } from './counter.store';
|
58
|
63
|
|
59
|
|
-const CounterScreen = observer(() => {
|
60
|
|
- const { count, increment, decrement } = React.useContext(CounterStoreContext)
|
|
64
|
+const CounterScreen = observer((props) => {
|
|
65
|
+ const { count, increment, decrement } = React.useContext(CounterStoreContext);
|
61
|
66
|
|
62
|
67
|
return (
|
63
|
|
- <View>
|
|
68
|
+ <Root>
|
64
|
69
|
<Text>{`Clicked ${count} times!`}</Text>
|
65
|
|
- <Button title="Increment" onPress={increment} />
|
66
|
|
- <Button title="Decrement" onPress={decrement} />
|
67
|
|
- </View>
|
|
70
|
+ <Button title='Increment' onPress={increment} />
|
|
71
|
+ <Button title='Decrement' onPress={decrement} />
|
|
72
|
+ <Button title='Push' onPress={() => Navigation.push(props.componentId, 'CounterScreen')}/>
|
|
73
|
+ </Root>
|
68
|
74
|
)
|
69
|
|
-})
|
|
75
|
+});
|
|
76
|
+module.exports = CounterScreen;
|
70
|
77
|
```
|
71
|
78
|
|
72
|
79
|
## How to use MobX persistent data
|
|
@@ -75,43 +82,42 @@ It only takes few extra steps to integrate the library.
|
75
|
82
|
|
76
|
83
|
```tsx
|
77
|
84
|
//counter.store.js
|
78
|
|
-import React from 'react'
|
79
|
|
-import { observable, action } from 'mobx'
|
80
|
|
-import { persist } from 'mobx-persist' // add this.
|
|
85
|
+import React from 'react';
|
|
86
|
+import { observable, action } from 'mobx';
|
|
87
|
+import { persist } from 'mobx-persist'; // add this.
|
81
|
88
|
|
82
|
89
|
class CounterStore {
|
83
|
|
- @persist @observable count = 0 // count is now persistent.
|
|
90
|
+ @persist @observable count = 0; // count is now persistent.
|
84
|
91
|
|
85
|
92
|
@action.bound
|
86
|
93
|
increment() {
|
87
|
|
- this.count += 1
|
|
94
|
+ this.count += 1;
|
88
|
95
|
}
|
89
|
96
|
|
90
|
97
|
@action.bound
|
91
|
98
|
decrement() {
|
92
|
|
- this.count -= 1
|
|
99
|
+ this.count -= 1;
|
93
|
100
|
}
|
94
|
101
|
}
|
95
|
102
|
|
96
|
|
-export const counterStore = new CounterStore() // You need to export the counterStore instance.
|
97
|
|
-export const CounterStoreContext = React.createContext(counterStore)
|
|
103
|
+export const counterStore = new CounterStore(); // You need to export the counterStore instance.
|
|
104
|
+export const CounterStoreContext = React.createContext(counterStore);
|
98
|
105
|
|
99
|
106
|
// index.js
|
100
|
|
-import { Navigation } from 'react-native-navigation
|
101
|
|
-import AsyncStorage from '@react-native-community/async-storage'
|
102
|
|
-import { create } from 'mobx-persist'
|
103
|
|
-import { counterStore } from './counter.store // import the counter store instance.
|
|
107
|
+import { Navigation } from 'react-native-navigation';
|
|
108
|
+import AsyncStorage from '@react-native-community/async-storage';
|
|
109
|
+import { create } from 'mobx-persist';
|
|
110
|
+import { counterStore } from './counter.store'; // import the counter store instance.
|
104
|
111
|
|
105
|
112
|
// Create a store hydration function.
|
106
|
113
|
async function hydrateStores() {
|
107
|
|
- const hydrate = create({ storage: AsyncStorage })
|
108
|
|
-
|
109
|
|
- await hydrate('CounterStore', counterStore)
|
|
114
|
+ const hydrate = create({ storage: AsyncStorage });
|
|
115
|
+ await hydrate('CounterStore', counterStore);
|
110
|
116
|
}
|
111
|
117
|
|
112
|
118
|
Navigation.events().registerAppLaunchedListener(() => {
|
113
|
119
|
hydrateStores().then(() => {
|
114
|
120
|
// ...register screens and start the app.
|
115
|
|
- })
|
116
|
|
-})
|
|
121
|
+ });
|
|
122
|
+});
|
117
|
123
|
```
|