├── .gitignore
├── .watchmanconfig
├── App.js
├── README.md
├── app.json
├── app
├── components
│ └── TaskListScreen.js
└── mobx
│ └── TaskListStore.js
├── assets
├── icon.png
└── splash.png
├── babel.config.js
├── package-lock.json
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/**/*
2 | .expo/*
3 | npm-debug.*
4 | *.jks
5 | *.p12
6 | *.key
7 | *.mobileprovision
8 |
--------------------------------------------------------------------------------
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import {
3 | Platform,
4 | StyleSheet,
5 | Text,
6 | View
7 | } from 'react-native';
8 |
9 | import TaskListScreen from './app/components/TaskListScreen'
10 |
11 | export default class App extends Component {
12 | render() {
13 | return ()
14 | }
15 | }
16 |
17 | const styles = StyleSheet.create({
18 | container: {
19 | flex: 1,
20 | justifyContent: 'center',
21 | alignItems: 'center',
22 | backgroundColor: '#F5FCFF',
23 | },
24 | welcome: {
25 | fontSize: 20,
26 | textAlign: 'center',
27 | margin: 10,
28 | },
29 | instructions: {
30 | textAlign: 'center',
31 | color: '#333333',
32 | marginBottom: 5,
33 | },
34 | });
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-native-expo-mobx
2 | React Native with Expo and MobX
3 |
4 | ## Step 1: Install packages:
5 | ```
6 | npm install --save mobx mobx-react
7 | ```
8 | ## Step 2: Install dev package and config it:
9 |
10 | ```
11 | npm install --save-dev @babel/plugin-proposal-decorators
12 | ```
13 |
14 | We need to add this plugin to `babel.config.js` like bellow:
15 |
16 | ```
17 | module.exports = function(api) {
18 | api.cache(true);
19 | return {
20 | presets: ['babel-preset-expo'],
21 | plugins: [
22 | [
23 | "@babel/plugin-proposal-decorators",
24 | {
25 | "legacy": true
26 | }
27 | ]
28 | ]
29 | };
30 | };
31 |
32 | ```
33 |
34 | ## Step 3: Create store and use it:
35 |
36 | **TaskListStore.js:**
37 |
38 |
39 | ```
40 |
41 | import { observable, action } from 'mobx'
42 |
43 | class TaskListStore {
44 |
45 | @observable list = [
46 | { title: 'Go to the School', isFinished: true },
47 | { title: 'Prepare tasks for today', isFinished: false },
48 | { title: 'Team meeting', isFinished: false },
49 | { title: 'Commit tasks changed', isFinished: false }
50 | ]
51 |
52 | @action finishItem (index) {
53 | const copiedList = this.list.slice()
54 | const isFinished = copiedList[index].isFinished
55 | if (isFinished) return
56 |
57 | copiedList[index].isFinished = true
58 | this.list = copiedList // update store by re-assigning
59 | }
60 |
61 | @action deleteItem (index) {
62 | this.list = this.list.filter((item, i) => i != index)
63 | }
64 | }
65 |
66 | const store = new TaskListStore()
67 | export default store
68 |
69 |
70 | ```
71 |
72 | **TaskListScreen.js:**
73 |
74 | ```
75 | import React, { Component } from 'react'
76 | import {
77 | StyleSheet,
78 | Text,
79 | TouchableOpacity,
80 | FlatList,
81 | View
82 | } from 'react-native'
83 |
84 | import taskListStore from './../mobx/TaskListStore'
85 | import { observer } from 'mobx-react/native'
86 |
87 | @observer
88 | export default class TaskListScreen extends Component {
89 |
90 | renderItem = ({ item, index }) => {
91 | return (
92 |
93 |
94 | taskListStore.finishItem(index)}>
95 | {(item.isFinished) ? `✅` : `🕘`}
96 |
97 |
98 |
99 | {item.title}
100 |
101 |
102 | taskListStore.deleteItem(index)}>
103 | {`❌`}
104 |
105 |
106 |
107 | )
108 | }
109 |
110 | render() {
111 | const list = taskListStore.list.slice() // don't forget copy the list from store
112 |
113 | return (
114 | `${index}`}
119 | renderItem={this.renderItem}
120 | />
121 | )
122 | }
123 | }
124 |
125 |
126 |
127 | ```
128 |
129 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "expo": {
3 | "name": "HelloExpo",
4 | "slug": "HelloExpo",
5 | "privacy": "public",
6 | "sdkVersion": "31.0.0",
7 | "platforms": [
8 | "ios",
9 | "android"
10 | ],
11 | "version": "1.0.0",
12 | "orientation": "portrait",
13 | "icon": "./assets/icon.png",
14 | "splash": {
15 | "image": "./assets/splash.png",
16 | "resizeMode": "contain",
17 | "backgroundColor": "#ffffff"
18 | },
19 | "updates": {
20 | "fallbackToCacheTimeout": 0
21 | },
22 | "assetBundlePatterns": [
23 | "**/*"
24 | ],
25 | "ios": {
26 | "supportsTablet": true
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/app/components/TaskListScreen.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import {
3 | StyleSheet,
4 | Text,
5 | TouchableOpacity,
6 | FlatList,
7 | View
8 | } from 'react-native'
9 |
10 | import taskListStore from './../mobx/TaskListStore'
11 | import { observer } from 'mobx-react/native'
12 |
13 | @observer
14 | export default class TaskListScreen extends Component {
15 |
16 | renderItem = ({ item, index }) => {
17 | return (
18 |
19 |
20 | taskListStore.finishItem(index)}>
21 | {(item.isFinished) ? `✅` : `🕘`}
22 |
23 |
24 |
25 | {item.title}
26 |
27 |
28 | taskListStore.deleteItem(index)}>
29 | {`❌`}
30 |
31 |
32 |
33 | )
34 | }
35 |
36 | render() {
37 | const list = taskListStore.list.slice() // don't forget copy the list from store
38 |
39 | return (
40 | `${index}`}
45 | renderItem={this.renderItem}
46 | />
47 | )
48 | }
49 | }
50 |
51 | const styles = StyleSheet.create({
52 | container: {
53 | flex: 1,
54 | backgroundColor: '#E1F5FE',
55 | paddingTop: 20
56 | },
57 | itemContainer: {
58 | flexDirection: 'row',
59 | alignItems: 'center',
60 | backgroundColor: 'white',
61 | marginHorizontal: 10,
62 | marginTop: 10,
63 | paddingHorizontal: 10,
64 | paddingVertical: 15,
65 | borderRadius: 5,
66 | borderColor: 'gray',
67 | shadowOffset: { width: 0, height: 1 },
68 | shadowOpacity: 0.2,
69 | shadowColor: 'gray',
70 | elevation: 2
71 | }
72 | })
--------------------------------------------------------------------------------
/app/mobx/TaskListStore.js:
--------------------------------------------------------------------------------
1 | import { observable, action } from 'mobx'
2 |
3 | class TaskListStore {
4 |
5 | @observable list = [
6 | { title: 'Go to the School', isFinished: true },
7 | { title: 'Prepare tasks for today', isFinished: false },
8 | { title: 'Team meeting', isFinished: false },
9 | { title: 'Commit tasks changed', isFinished: false }
10 | ]
11 |
12 | @action finishItem (index) {
13 | const copiedList = this.list.slice()
14 | const isFinished = copiedList[index].isFinished
15 | if (isFinished) return
16 |
17 | copiedList[index].isFinished = true
18 | this.list = copiedList // update store by re-assigning
19 | }
20 |
21 | @action deleteItem (index) {
22 | this.list = this.list.filter((item, i) => i != index)
23 | }
24 | }
25 |
26 | const store = new TaskListStore()
27 | export default store
--------------------------------------------------------------------------------
/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodeMasterChef/react-native-expo-mobx/385ca2e29f68d699f3f00cfc8f558ae9a421e5f6/assets/icon.png
--------------------------------------------------------------------------------
/assets/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodeMasterChef/react-native-expo-mobx/385ca2e29f68d699f3f00cfc8f558ae9a421e5f6/assets/splash.png
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function(api) {
2 | api.cache(true);
3 | return {
4 | presets: ['babel-preset-expo'],
5 | plugins: [
6 | [
7 | "@babel/plugin-proposal-decorators",
8 | {
9 | "legacy": true
10 | }
11 | ]
12 | ]
13 | };
14 | };
15 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "main": "node_modules/expo/AppEntry.js",
3 | "scripts": {
4 | "start": "expo start",
5 | "android": "expo start --android",
6 | "ios": "expo start --ios",
7 | "eject": "expo eject"
8 | },
9 | "dependencies": {
10 | "expo": "^31.0.2",
11 | "mobx": "^5.6.0",
12 | "mobx-react": "^5.4.2",
13 | "react": "16.5.0",
14 | "react-native": "https://github.com/expo/react-native/archive/sdk-31.0.0.tar.gz"
15 | },
16 | "devDependencies": {
17 | "@babel/plugin-proposal-decorators": "^7.1.6",
18 | "babel-preset-expo": "^5.0.0",
19 | "babel-preset-react-native-stage-0": "^1.0.1"
20 | },
21 | "private": true
22 | }
23 |
--------------------------------------------------------------------------------