Skip to content

Instantly share code, notes, and snippets.

@mujuni88
Last active September 18, 2018 15:47
Show Gist options
  • Save mujuni88/03c001a72685ba848ed3fd3a908f8b3d to your computer and use it in GitHub Desktop.
Save mujuni88/03c001a72685ba848ed3fd3a908f8b3d to your computer and use it in GitHub Desktop.
Store Template
/*
* Example of an entity/model class
*/
import {
observable,
action
} from 'mobx'
import { setter } from 'mobx-decorators'
export class Entity {
id = null
parentStore = null
@setter
@observable
name = ''
constructor(parentStore, config) {
this.parentStore = parentStore // optional.
this.updateFromJson(config)
}
@action
updateFromJson({ id, name }) {
this.id = id
this.name = name
}
@action
delete = () => {
this.parentStore.delete(this)
}
}
/*
* The Store is responsible for the following:
* 1. Holding the state of entities
* 2. Fetching entities
* 3. Creating entities
* 4. Deleting entities
* 5. Updating entities
*
* An Entity could be an object or a class.
* Prefer using Entity classes because you can do more with them.
*/
import { observable, action, autorun, computed } from 'mobx'
import { setter } from 'mobx-decorators'
import xhr from 'helpers/XHR'
import uiStore from 'stores/UiStore'
import getError from 'helpers/ErrorParser'
import Entity from 'stores/models/Entity'
/*
* Example of a store
*/
export class StoreTemplate {
@setter
@observable
isLoading = false
@setter
@observable
isError = false
@observable
entities = observable.map() // array could work to
contructor() {
this.initAutoruns()
}
// Computed
@computed
get hasErrors() {
return !this.isLoading && this.isError
}
// Actions
/*
* All autoruns are initialized in this function
*/
@action
initAutoruns = () => {
this.autoErrorNotifier()
}
/*
* This autorun will be ran automatically whenever the [observable] property [isError] is changed.
* This will automatically show a notification message to the user
*/
@action
autoErrorNotifier = () => {
this.autoErrorDisposer = autorun('Watch errors', () => {
if (this.isError && !this.isError.hideNotification) {
uiStore.addNotification({
title: this.isError.title,
message: this.isError.message,
type: this.isError.type || 'error'
})
}
})
}
/*
* CRUD operations that the store is responsible for
*/
@action
createEntity = json => {
this.entities.set(json.id, new Entity(this, json))
}
@action
deleteEntity = entity => {
this.entities.delete(entity.id)
}
@action
updateEntity = json => {
const entity = this.entities.get(json.id)
entity && entity.update(json)
}
/*
* Example of a XHR get function.
*
* Important things:
* 1. Clear errors before fetching
* 2. Set loading before fetching
* 3. Catch errors in the catch block
* 4. Clear loading in the finally block
* 5. MOST IMPORTANT: After a response, all changes are placed inside an action function fetchExampleOK.
*/
@action
fetchExample = async () => {
try {
this.setIsLoading(true)
this.setIsError(false)
const response = await xhr.get('/groups', {
params: {
type: 'user'
}
})
this.fetchExampleOK(response)
} catch (e) {
this.setIsError(getError(e))
} finally {
this.setIsLoading(false)
}
}
@action
fetchExampleOK = response => {
console.log(response.header)
console.log(response.data)
response.data.forEach(this.createEntity)
}
/*
* Example of a XHR post function.
*
* Important things:
* 1. Clear errors before fetching
* 2. Set loading before fetching
* 3. Catch errors in the catch block
* 4. Clear loading in the finally block
* 5. MOST IMPORTANT: After a response, all changes are placed inside an action function postExampleOK.
*/
@action
postExample = async () => {
try {
this.setIsLoading(true)
this.setIsError(false)
const data = { id: 1, body: 'Hello world' }
const response = await xhr.post('/groups', data)
this.postExampleOK(response)
} catch (e) {
this.setIsError(getError(e))
} finally {
this.setIsLoading(false)
}
}
@action
postExampleOK = response => {
console.log(response.header)
console.log(response.data)
response.data.forEach(this.updateEntity)
}
/*
* dispose all autoruns here to avoid subtle memory leak issues
*/
@action
dispose = () => {
this.autoErrorNotifier && this.autoErrorNotifier()
}
}
export default new StoreTemplate()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment