Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Next level Vuex

Next level Vuex

Niklas Lochschmidt

February 07, 2019
Tweet

More Decks by Niklas Lochschmidt

Other Decks in Programming

Transcript

  1. @Niklas_L #VueJSfrankfurt Cmd + Z Cmd + Y • Provides

    safety for users • Ubiquitous in Desktop applications • Not so much in mobile and web applications !
  2. @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?
  3. @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.”
  4. @Niklas_L #VueJSfrankfurt “There are actions I don't want undo for.

    Say, user toggles a grid view in the editor.”
  5. @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
  6. @Niklas_L #VueJSfrankfurt Option A: State snapshots • Every change causes

    snapshot to be stored • Reverting means restoring earlier snapshot Pro: Simple implementation Cons: ?
  7. @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
  8. @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
  9. @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 !
  10. @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); };
  11. @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
  12. @Niklas_L #VueJSfrankfurt Revisiting the Vuex architecture • Components dispatch Actions

    • Actions commit Mutations • Mutations mutate State • State renders to Component
  13. @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
  14. @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
  15. @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
  16. @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
  17. @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