import mobx from 'mobx'
// Very naive concept of performant mobx undo
var history = []
// Let's say mobx have observeAll function acting as observe, but on all mobx observable entities.
// `change` object would need to have `observedType` key.
// It would also observe primitive observables.
mobx.observeAll((change) => {
history.push(change)
})
function getHistoryPosition() {
return history.length
}
function backToHistoryPosition(index) {
while(history.length > index) {
const change = history.pop()
undoChange(change)
}
}
function undoChange(change) {
switch(change.observedType) {
case 'map':
switch (change.type) {
case 'add':
change.object.delete(change.name)
return
case 'delete':
change.object.set(change.name, change.oldValue)
return
case 'update':
change.object.set(change.name, change.oldValue)
return
}
case 'array':
// similar to map case
case 'primitive':
// similar to map case
case 'object':
// similar to map case
// ? here we would need mobx.unextendObservable to reverse mobx.extendObservable ?
default:
invariant( false, 'change object should be like object returned by `mobx.observe` with added key `observedType`')
}
}
// Then it can be used like:
const state = myLib.createMyFancyStore()
function actionOnButtonClick() {
let historyBeforeUpdate = getHistoryPosition()
state.optimisticallyUpdate()
state.sendUpdateToServer((err) => {
if(err) {
// If action didn't come through we can roll it back
backToHistoryPosition(historyBeforeUpdate)
}
})
}