Skip to content

Instantly share code, notes, and snippets.

@DawidMyslak
Last active April 22, 2024 12:49
Show Gist options
  • Select an option

  • Save DawidMyslak/2b046cca5959427e8fb5c1da45ef7748 to your computer and use it in GitHub Desktop.

Select an option

Save DawidMyslak/2b046cca5959427e8fb5c1da45ef7748 to your computer and use it in GitHub Desktop.

Revisions

  1. Dawid Myslak revised this gist Jul 7, 2021. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions vue.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    # Vue.js and Vuex - best practices for managing your state

    ## Modyfing state object
    ## Modifying state object

    ### Example

    @@ -60,7 +60,7 @@ When your application gets bigger over time and your state becomes more complex,

    Same rules apply to nested objects and their properties, so prefer flat structure when you are designing your store schema.

    ## Modyfing state array
    ## Modifying state array

    ### Example

    @@ -90,7 +90,7 @@ const store = new Vuex.Store({
    // more details: https://vuejs.org/v2/guide/list.html#Replacing-an-Array
    state.users = [...state.users, {name}]
    },
    updateUserAvatar (state, index, avatar) {
    updateUserAvatar (state, {index, avatar}) {
    // 1st solution:
    // it will properly update an array item, but also it will trigger getUsersNames()
    Vue.set(state.users[index], 'avatar', avatar)
  2. Dawid Myslak revised this gist Apr 9, 2019. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions vue.md
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@

    ### Example

    If you have to extend an existing object with additional property, always prefer `Vue.set()` over `Object.assing()` (or spread operator).
    If you have to extend an existing object with additional property, always prefer `Vue.set()` over `Object.assign()` (or spread operator).

    Example below explains implications for different implementations.

    @@ -27,7 +27,7 @@ const store = new Vuex.Store({
    state.user.name = name

    // 2nd solution:
    // same as "state.user = Object.assing({}, state.user, { name })"
    // same as "state.user = Object.assign({}, state.user, { name })"
    // it will trigger both getters every time when you call this mutation
    state.user = { ...state.user, name }

  3. Dawid Myslak revised this gist Sep 25, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion vue.md
    Original file line number Diff line number Diff line change
    @@ -111,4 +111,4 @@ Be aware that adding a new item to an existing state array will always trigger a

    When you add or remove items from an array it's okay to recreate the array entirely - feel free to use latest JavaScript features like spread operator or simply call array's mutation methods like `push()`.

    Different rules apply when you update existing object inside an array. First of all, declare all object properties (even with `null` values) before you add it to the array, they will become reactive properties observed by Vue. Avoid adding new properties to the object, it will always trigger all getters that are based on the array. You should modify object properites directly (for example `state.users[index].avatar = avatar`) and avoid recreating the entire array for updates.
    Different rules apply when you update existing object inside an array. First of all, declare all object properties (even with `null` values) before you add it to the array, they will become reactive properties observed by Vue. Avoid adding new properties to the object, it will always trigger all getters that are based on the array. You should modify object properites directly (for example `state.users[0].name = "Test"`) and avoid recreating the entire array for updates.
  4. Dawid Myslak revised this gist Sep 25, 2017. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions vue.md
    Original file line number Diff line number Diff line change
    @@ -99,7 +99,7 @@ const store = new Vuex.Store({
    // it's going to work only if we modify addUser() function and include avatar property there:
    // "state.users.push({name, avatar: null})"
    // the benefit of this approach is that getUsersNames() won't be triggered
    state.users[index].avatar = avatar;
    state.users[index].avatar = avatar
    }
    }
    })
    @@ -111,4 +111,4 @@ Be aware that adding a new item to an existing state array will always trigger a

    When you add or remove items from an array it's okay to recreate the array entirely - feel free to use latest JavaScript features like spread operator or simply call array's mutation methods like `push()`.

    Different rules apply when you update existing object inside an array. First of all, declare all object properties (even with `null` values) before you add it to the array, they will become reactive properties observed by Vue. Avoid adding new properties to the object, it will always trigger all getters that are based on the array. Modify object properites directly don't recreate the entire array .
    Different rules apply when you update existing object inside an array. First of all, declare all object properties (even with `null` values) before you add it to the array, they will become reactive properties observed by Vue. Avoid adding new properties to the object, it will always trigger all getters that are based on the array. You should modify object properites directly (for example `state.users[index].avatar = avatar`) and avoid recreating the entire array for updates.
  5. Dawid Myslak revised this gist Sep 25, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion vue.md
    Original file line number Diff line number Diff line change
    @@ -107,7 +107,7 @@ const store = new Vuex.Store({

    ### Summary

    Be aware that adding a new item to an existing state array will trigger all getters (and computed properties) which are based on that array. Same will happen if you remove the item.
    Be aware that adding a new item to an existing state array will always trigger all getters (and computed properties) which are based on that array. Same will happen if you remove the item.

    When you add or remove items from an array it's okay to recreate the array entirely - feel free to use latest JavaScript features like spread operator or simply call array's mutation methods like `push()`.

  6. Dawid Myslak revised this gist Sep 25, 2017. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion vue.md
    Original file line number Diff line number Diff line change
    @@ -85,7 +85,8 @@ const store = new Vuex.Store({
    state.users.push({name})

    // 2nd solution
    // even though we are recreating the entire array, it will behave in the same way as first solution
    // even though we are recreating the entire array,
    // it will behave in the same way as first solution
    // more details: https://vuejs.org/v2/guide/list.html#Replacing-an-Array
    state.users = [...state.users, {name}]
    },
  7. Dawid Myslak revised this gist Sep 25, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion vue.md
    Original file line number Diff line number Diff line change
    @@ -58,7 +58,7 @@ Be aware that adding a new property to an existing state object can have a signi

    When your application gets bigger over time and your state becomes more complex, try to use [modules](https://vuex.vuejs.org/en/modules.html) for better data encapsulation. So even if you have to add a new property at least it will have an impact only on a single module.

    Same rules apply to nested objects and their properties, so when you are designing your store schema prefer flat structure.
    Same rules apply to nested objects and their properties, so prefer flat structure when you are designing your store schema.

    ## Modyfing state array

  8. Dawid Myslak revised this gist Sep 25, 2017. 1 changed file with 12 additions and 1 deletion.
    13 changes: 12 additions & 1 deletion vue.md
    Original file line number Diff line number Diff line change
    @@ -66,6 +66,8 @@ Same rules apply to nested objects and their properties, so when you are designi

    If you have to add a new object to an existing array, always define all potential properties of the object upfront even if you do not know their values at the time.

    Check the example below for more details.

    ```javascript
    const store = new Vuex.Store({
    state: {
    @@ -93,10 +95,19 @@ const store = new Vuex.Store({
    Vue.set(state.users[index], 'avatar', avatar)

    // 2nd solution:
    // it is going to work only if we modify addUser() function and include avatar property there: "state.users.push({name, avatar: null})"
    // it's going to work only if we modify addUser() function and include avatar property there:
    // "state.users.push({name, avatar: null})"
    // the benefit of this approach is that getUsersNames() won't be triggered
    state.users[index].avatar = avatar;
    }
    }
    })
    ```

    ### Summary

    Be aware that adding a new item to an existing state array will trigger all getters (and computed properties) which are based on that array. Same will happen if you remove the item.

    When you add or remove items from an array it's okay to recreate the array entirely - feel free to use latest JavaScript features like spread operator or simply call array's mutation methods like `push()`.

    Different rules apply when you update existing object inside an array. First of all, declare all object properties (even with `null` values) before you add it to the array, they will become reactive properties observed by Vue. Avoid adding new properties to the object, it will always trigger all getters that are based on the array. Modify object properites directly don't recreate the entire array .
  9. Dawid Myslak revised this gist Sep 25, 2017. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion vue.md
    Original file line number Diff line number Diff line change
    @@ -32,7 +32,8 @@ const store = new Vuex.Store({
    state.user = { ...state.user, name }

    // 3rd solution:
    // it will trigger both getters when you call this mutation for the first time, but if you call it the next time only getUserName() will be triggered
    // it will trigger both getters when you call this mutation for the first time,
    // but if you call it the next time only getUserName() will be triggered
    // Vue.set() will check if property already exists before re-assigning the entire object
    Vue.set(state.user, 'name', name)
    }
  10. Dawid Myslak renamed this gist Sep 25, 2017. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  11. Dawid Myslak created this gist Sep 25, 2017.
    101 changes: 101 additions & 0 deletions md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,101 @@
    # Vue.js and Vuex - best practices for managing your state

    ## Modyfing state object

    ### Example

    If you have to extend an existing object with additional property, always prefer `Vue.set()` over `Object.assing()` (or spread operator).

    Example below explains implications for different implementations.

    ```javascript
    const store = new Vuex.Store({
    state: {
    user: {
    id: 1
    }
    },
    getters: {
    getUserId: state => state.user.id,
    getUserName: state => state.user.name
    },
    mutations: {
    setUserName (state, name) {
    // 1st solution:
    // it won't trigger getters at all, more details:
    // https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats
    state.user.name = name

    // 2nd solution:
    // same as "state.user = Object.assing({}, state.user, { name })"
    // it will trigger both getters every time when you call this mutation
    state.user = { ...state.user, name }

    // 3rd solution:
    // it will trigger both getters when you call this mutation for the first time, but if you call it the next time only getUserName() will be triggered
    // Vue.set() will check if property already exists before re-assigning the entire object
    Vue.set(state.user, 'name', name)
    }
    }
    })
    ```

    Ideally, try to initialize your state with all desired fields upfront, so in the example above `state` should be declared in the following way:

    ```javascript
    state: {
    user: {
    id: 1,
    name: null
    }
    }
    ```

    ### Summary

    Be aware that adding a new property to an existing state object can have a significant impact on your application performance. It will trigger all getters based on that object (and potentially computed properties declared inside your componets).

    When your application gets bigger over time and your state becomes more complex, try to use [modules](https://vuex.vuejs.org/en/modules.html) for better data encapsulation. So even if you have to add a new property at least it will have an impact only on a single module.

    Same rules apply to nested objects and their properties, so when you are designing your store schema prefer flat structure.

    ## Modyfing state array

    ### Example

    If you have to add a new object to an existing array, always define all potential properties of the object upfront even if you do not know their values at the time.

    ```javascript
    const store = new Vuex.Store({
    state: {
    users: []
    },
    getters: {
    getUsersNames: state => {
    return state.users.map(user => user.name)
    }
    },
    mutations: {
    addUser (state, name) {
    // 1st solution:
    // it will work as expected and trigger getUsersNames()
    state.users.push({name})

    // 2nd solution
    // even though we are recreating the entire array, it will behave in the same way as first solution
    // more details: https://vuejs.org/v2/guide/list.html#Replacing-an-Array
    state.users = [...state.users, {name}]
    },
    updateUserAvatar (state, index, avatar) {
    // 1st solution:
    // it will properly update an array item, but also it will trigger getUsersNames()
    Vue.set(state.users[index], 'avatar', avatar)

    // 2nd solution:
    // it is going to work only if we modify addUser() function and include avatar property there: "state.users.push({name, avatar: null})"
    // the benefit of this approach is that getUsersNames() won't be triggered
    state.users[index].avatar = avatar;
    }
    }
    })
    ```