This is a very simple, quick and easy tutorial on React Native using MobX for you to get started on the go!
First create a simple react native project using the following link
https://reactnative.dev/docs/environment-setup. Yeah beginner's steps lol!
Now run your simple init react native project. Just to make sure that your project is atleast up and running. Okay so first step is done. We have our another simple react native project. Woohoo!
Now let's try integrating MobX!
Let's first get a quick overview of what MobX really is!
MobX is state management library. It means that it handles and manages app state throughout the application.
I have found Redux, ReactHooks and MobX as the most popular state management libraries for React and ReactNative.
To get to know the idea and difference between these follow this link Why we shifted from Redux to MobX (logicwind.com)
Both Redux and MobX does almost the same thing. But MobX is easy 😎.
Advantages:
- Easy to setup
- Easy to explain
- Easy to manage
- No boiler plate
- Magical Rendering
- And yeah all the good stuff
Now's let get started!
Open your regular code editor. (I personally prefer VSCode and of course with black theme 😜)
Okay so first you need to install two dependencies to get started which are mobx and mobx-react. Use this command npm install mobx mobx-react
And also you will need a DEV dependency npm install --save-dev @babel/plugin-proposal-decorators because MobX works on decorators.
Now in your project you will find a file babel.config.js
In that you will find a key preset. Add below code below this preset key
1"plugins": [2 [3 "@babel/plugin-proposal-decorators",4 {5 "legacy": true6 }7 ]8]
In the latest versions of MobX you may also need to add more configurations as given below in the image. You may add it if needed.
1module.exports = {2 presets: ['module:metro-react-native-babel-preset'],3 plugins: [4 ['@babel/plugin-transform-flow-strip-types'],5 [6 "@babel/plugin-proposal-decorators",7 {8 "legacy": true9 }10 ],11 ["@babel/plugin-proposal-class-properties",12 {13 "loose": false14 }]15 ]16};
Also you will have to enable Experimental Decorators in your code editor's setting. But it's not necessary. It's just for the red lines that might show up in your code editor
Let's begin with our regular stuff. Yeah that's right CODING!
In your project create a file call TodoStore.js
Something like this simple code given below
1import React from "react";2import { observable, action, computed, makeObservable } from "mobx";3import AsyncStorage from '@react-native-community/async-storage';45class TodoStore {67 @observable idForTodo = 3;89 @observable todos = [10 {11 id: 1,12 title: "Todo 1",13 completed: false14 },15 {16 id: 2,17 title: "Todo 2",18 completed: false19 },20 ];2122 constructor() {23 makeObservable(this)24 }2526 @action getData = async () => {27 const value = await AsyncStorage.getItem('TODOS')28 if (value !== null) {29 this.todos = JSON.parse(value)30 }31 }3233 @action addTodo = async (todoInput) => {34 this.todos.push({35 id: this.idForTodo,36 title: todoInput.trim(),37 completed: false38 });39 await AsyncStorage.setItem('TODOS', JSON.stringify(this.todos))40 this.idForTodo++;41 };4243 @action deleteTodo = async (id) => {44 const index = this.todos.findIndex((item) => item.id === id);45 this.todos.splice(index, 1);46 await AsyncStorage.setItem('TODOS', JSON.stringify(this.todos))47 };4849 @action checkTodo = async (todo) => {50 todo.completed = !todo.completed;51 const index = this.todos.findIndex((item) => item.id === todo.id);52 this.todos.splice(index, 1, todo);53 await AsyncStorage.setItem('TODOS', JSON.stringify(this.todos))54 };5556 @action checkAllTodos = async (value = true) => {57 this.todos.forEach((todo) => (todo.completed = value));58 await AsyncStorage.setItem('TODOS', JSON.stringify(this.todos))59 };6061 @computed get todosCompletedCount() {62 return this.todos.filter((todo) => todo.completed).length;63 }6465 @computed get remaining() {66 return this.todos.filter((todo) => !todo.completed).length;67 }6869}7071const store = new TodoStore();72export default store;
observable - an element whenever updates it will re-render wherever it is used in the application
action - it allows to create a function in the store which further updates the observable
computed - it is called automatically whenever an observable is updated
Great. We have created our first store! You can now create other stores in similar manner.
Now we have to wrap/bind this store to our application in our App.js as shown below using Provider from mobx-react
1import * as React from 'react';2import { Provider } from 'mobx-react';3import TodoStore from './TodoStore';4import Home from './Home';56class App extends React.Component {7 render() {8 <Provider todoStore={TodoStore} >9 <Home />10 </Provider>11 }12}
Now let's create a Home.js to get our simple Todo demo up and running using MobX functionality
PS: I have added react-native-swipe-item and react-native-elements just to have good UI/UX and clear idea of functional requirement
1import React, { Component } from 'react';2import { View, TextInput, SafeAreaView, StyleSheet, TouchableOpacity } from 'react-native';3import { SwipeItem, SwipeButtonsContainer } from 'react-native-swipe-item';4import { Header, ListItem, Text, Button } from 'react-native-elements';5import AsyncStorage from '@react-native-community/async-storage';6import { inject, observer } from 'mobx-react';78@inject('todoStore')9@observer10export default class Home extends Component {1112 constructor(props) {13 super(props)14 this.state = {15 text: ''16 }17 }1819 componentWillMount() {20 const { todoStore } = this.props21 todoStore.getData();22 }2324 onChangeText = (text) => {25 if (text && !!text) {26 this.setState({ text })27 }28 }2930 SubmitData = () => {31 try {32 const { text } = this.state33 if (text && !!text) {34 this.setState({ text: '' })35 const { todoStore } = this.props36 todoStore.addTodo(text)37 } else {38 alert('Please enter todo title!')39 }40 } catch (error) {41 alert('Something went wrong')42 }43 }4445 swipeRender = (index) => {46 return (47 <SwipeButtonsContainer style={styles.swipcercell}>48 <TouchableOpacity onPress={() => this.markTodo(index)} >49 <Text>Mark</Text>50 </TouchableOpacity>51 </SwipeButtonsContainer>52 );53 }5455 swipeDelete = (index) => {56 return (57 <SwipeButtonsContainer style={styles.swipcercell}>58 <TouchableOpacity onPress={() => this.deleteTodo(index)} >59 <Text>Delete</Text>60 </TouchableOpacity>61 </SwipeButtonsContainer>62 );63 }6465 markTodo = (index) => {66 const { todoStore } = this.props67 todoStore.checkTodo(todoStore.todos[index])68 }6970 deleteTodo = (index) => {71 const { todoStore } = this.props72 todoStore.deleteTodo(index)73 }7475 render() {76 const { todos, todosCompletedCount } = this.props.todoStore77 const { text } = this.state7879 return (80 <>81 <SafeAreaView style={styles.SafeAreaViewcontainer}>8283 <Header84 centerComponent={{ text: 'MY TODOS', style: { color: '#fff' } }}85 />8687 <View style={{ margin: 10 }}>88 <TextInput89 value={text}90 placeholder={'Add Todo'}91 onChangeText={this.onChangeText}92 />9394 <View style={styles.buttonrow}>95 <Text style={styles.todomaintitle}>todosCompletedCount()</Text>96 </View>9798 <View style={styles.buttonrow}>99 <Button100 title="Submit"101 containerStyle={styles.buttonsubmit}102 onPress={this.SubmitData}103 />104 </View>105106 {todos.length > 0 &&107 <>108 <View>109 <Text style={styles.todomaintitle}>My Todos</Text>110 </View>111 {todos.map((data, index) => {112 return (113 <SwipeItem114 key={index}115 style={styles.button}116 swipeContainerStyle={styles.swipeContentContainerStyle}117 leftButtons={() => this.swipeRender(index)}118 rightButtons={() => this.swipeDelete(index)}119 >120 <ListItem121 titleStyle={{ color: data.completed ? 'green' : 'red' }}122 style={styles.listiem}123 title={data.title}124 />125 </SwipeItem>126127 )128 })}129 </>130 }131 </View>132 </SafeAreaView>133 </>134 );135 }136}137138const styles = StyleSheet.create({139 SafeAreaViewcontainer: { flex: 1, width: '100%' },140 button: {141 alignItems: 'center',142 justifyContent: 'center',143 alignSelf: 'center',144 height: 55,145 marginTop: 10,146 backgroundColor: 'white',147 },148 swipcercell: {149 alignSelf: 'center',150 aspectRatio: 1,151 flexDirection: 'column',152 padding: 10,153 },154 swipeContentContainerStyle: {155 borderRadius: 10,156 borderColor: 'black',157 borderWidth: 1,158159 },160 listiem: {161 backgroundColor: 'white',162 borderColor: 'transparent', borderRadius: 10, width: '98%', paddingLeft: 10163 },164 buttonsubmit: {165 width: '100%',166 flex: 1,167 justifyContent: 'space-between',168 marginLeft: 10,169 marginRight: 10,170 marginTop: 20,171 marginBottom: 20,172 },173 buttonrow: {174 flexDirection: 'row'175 },176 todomaintitle: { fontSize: 20, fontWeight: 'bold', marginLeft: 10 }177});
inject - it will get the whole store in our Home Component
observer - it will allow our Home component to listen to the changes/updates made into the observable of our TodoStore
As you can see I have render todosCompletedCount() in Text component. This is a @computed function of our TodoStore. It will be called initially and whenever a observable is updated
Voila! We are done! That's all folks!
Yeah it's that simple and easy!
Hope you find it useful!
Thanks for reading!



.png&w=3840&q=75)