July 07, 2021
yarn add mobx mobx-react-lite
// or
npm install mobx mobx-react-lite
Store example - ItemsStore.js
import { makeAutoObservable, runInAction } from 'mobx'
const fakeItems = [
{
id: '13asd3',
title: 'Item 1',
},
{
id: '23asr3',
title: 'Item 2',
},
]
export default class ItemsStore {
items = []
loading = false
error = null
constructor() {
makeAutoObservable(this)
}
get count() {
return this.items.length
}
// async call example
fetchItems = async () => {
this.loading = true
try {
// simulates data fetching
const data = await new Promise(resolve => setTimeout(() => resolve(fakeItems), 3000))
runInAction(() => {
this.items = data
this.loading = false
this.error = null
})
} catch (error) {
runInAction(() => {
this.error = error
})
}
}
}
Export stores, StoreProvider, and useStore hook - stores.js
import { createContext, useContext } from 'react'
import ItemsStore from './ItemsStore'
export const stores = Object.freeze({
itemsStore: new ItemsStore(),
})
const storeContext = createContext(stores)
export const StoreProvider = storeContext.Provider
export const useStore = store => useContext(storeContext)[store]
Wrap the app or component/s with StoreProvider - App.js
import React from 'react'
import { StoreProvider, stores } from './stores'
import List from './List'
const App = () => {
return (
<StoreProvider value={stores}>
<List />
</StoreProvider>
)
}
export default App
Component example - List.js
import React, { useEffect } from 'react'
import { observer } from 'mobx-react-lite'
import { useStore } from './stores'
const List = () => {
const { items, loading, fetchItems, count } = useStore('itemsStore')
useEffect(() => {
if (!count) fetchItems()
}, [count, fetchItems])
return (
<>
{loading ? (
<p>loading...</p>
) : (
<div>
{items.map(({ id, title }) => (
<p key={id}>{title}</p>
))}
</div>
)}
</>
)
}
export default observer(List)