Next level Vuex

Next level Vuex

39ef6987e0b00c12a1af3f8e9a5a5e73?s=128

Niklas Lochschmidt

February 07, 2019
Tweet

Transcript

  1. @Niklas_L #VueJSfrankfurt Next level Vuex Undo & Redo for your

    Users Niklas Lochschmidt
  2. @Niklas_L #VueJSfrankfurt Cmd + Z Cmd + Y • Provides

    safety for users • Ubiquitous in Desktop applications • Not so much in mobile and web applications !
  3. @Niklas_L #VueJSfrankfurt Sounds simple Start !

  4. @Niklas_L #VueJSfrankfurt Vuex Devtools Demo Branch demo1 on h-ps://gitlab.com/nlochschmidt/vuex-undo-redo-talk

  5. @Niklas_L #VueJSfrankfurt Aha not so simple… • Where does a

    step start, where does it end • Not everything can be undone • Not everything can be redone • How many steps do we allow to go back • Also: What about side effects?
  6. @Niklas_L #VueJSfrankfurt First order of business: Check npmjs.com

  7. @Niklas_L #VueJSfrankfurt “I have some actions that fire many, many

    times … obviously it would make sense to undo the entire move instead of doing it one by one.”
  8. @Niklas_L #VueJSfrankfurt “There are actions I don't want undo for.

    Say, user toggles a grid view in the editor.”
  9. @Niklas_L #VueJSfrankfurt “Race condition with undo/redo … the undo operations

    are intertwined”
  10. @Niklas_L #VueJSfrankfurt What do we do at BRYTER? More infos

    at bryter.io
  11. @Niklas_L #VueJSfrankfurt Types of changes in the application • UI

    state only select a node • Single mutations change a node title • Mixture select a node then highlight immediately • Multiple mutations insert a node between nodes • Side-effect actions upload image to server
  12. @Niklas_L #VueJSfrankfurt Option A: State snapshots • Every change causes

    snapshot to be stored • Reverting means restoring earlier snapshot Pro: Simple implementation Cons: ?
  13. @Niklas_L #VueJSfrankfurt Demo See branch demo2 https://gitlab.com/nlochschmidt/vuex-undo-redo-talk

  14. @Niklas_L #VueJSfrankfurt Spot the bug // todoList/mutations.js const saveTodoSnapshot =

    state => { state.undo.redoStates = []; state.undo.undoStates.push(state.todos); }; ⚠ Shared mutable state is hard
  15. @Niklas_L #VueJSfrankfurt Spot the bug // todoList/mutations.js const saveTodoSnapshot =

    state => { state.undo.redoStates = []; state.undo.undoStates.push(deepCopy(state.todos)); }; ⚠ Shared mutable state is hard
  16. @Niklas_L #VueJSfrankfurt Demo See branch demo2.1 https://gitlab.com/nlochschmidt/vuex-undo-redo-talk

  17. @Niklas_L #VueJSfrankfurt Option A: State snapshots • Every change causes

    snapshot to be stored • Reverting means restoring earlier snapshot Pro: Simple implementation Cons: Memory footprint !
  18. @Niklas_L #VueJSfrankfurt Option B: Forward and backward mutations const addTodo

    = (state, { title }) => { const id = createId(); Vue.set(state.todos, id, { id, title, completed: false }); }; const removeTodo = (state, { id }) => { saveUndoMutation({ undo: { type: "addTodo", payload: { title: state.todos[id].title } }, redo: { type: "removeTodo", payload: { id } } }); Vue.delete(state.todos, id); };
  19. @Niklas_L #VueJSfrankfurt Option B: Forward and backward mutations • Implement

    how to mutate the state • and how to revert the mutation again Pro: • Smaller memory overhead, minimal processing Cons: • Specific mutations just for the sake of undo • Twice the implementation per mutation
  20. @Niklas_L #VueJSfrankfurt Revisiting the Vuex architecture • Components dispatch Actions

    • Actions commit Mutations • Mutations mutate State • State renders to Component
  21. @Niklas_L #VueJSfrankfurt • UI dispatches Commands • Commands cause Events

    • Events update Read-Models • Read-Models render to UI Commands Events Read Model UI dispatch cause update render Command Query Responsibility Segregation and Event Sourcing
  22. @Niklas_L #VueJSfrankfurt Undo: Replay all mutations from base state Base

    State Replay
  23. @Niklas_L #VueJSfrankfurt Redo: Replay next mutation(s) Base State Replay Current

    State
  24. @Niklas_L #VueJSfrankfurt New mutation clears the undo stack Base State

    Current State
  25. @Niklas_L #VueJSfrankfurt Vuex Plugins const myPlugin = store => {

    store.registerModule("myModule", module); // register a module dynamically store.subscribe((mutation, state) => {...}); // called after every mutation store.subscribeAction({ before: (action, state) => {...}, // called before the action is executed after: (action, state) => {...} // called after action has resolved }); }; const store = new Vuex.Store({ ... plugins: [myPlugin] }); h"ps://vuex.vuejs.org/guide/plugins.html
  26. @Niklas_L #VueJSfrankfurt Vuex Plugins • Plugins can only be added

    to the store not in modules • store.subscribe and subscribeAction always see mutations and actions with the complete namespace • Plugins will o!en need explicit configuration
  27. @Niklas_L #VueJSfrankfurt Demo See branches demo3, demo4 and demo5 https://gitlab.com/nlochschmidt/vuex-undo-redo-talk

  28. @Niklas_L #VueJSfrankfurt Option C: Base state + forward mutations •

    Save a base state for resetMutations • Replay all other mutations on top of the base state Pro: • Easy to generalize, moderate memory footprint Cons: • Potentially processing intensive • More complicated to setup
  29. @Niklas_L #VueJSfrankfurt Opinionated advise for using Vuex • Don‘t commit

    mutations from Vue Components • Instead always go through an action • Stay flexible • Protect your state changes • Perform validations before committing • Use objects as payload • Easy to add optional fields later • See mutations as past events • Manage complexity using namespaces Remember ⚠ Shared mutable state is hard
  30. @Niklas_L #VueJSfrankfurt Q&A • Slides and code will be available

    through meetup.com