How to reset to initial state in VueJS
How do we reset to the initial state in VueJS 3? Sometimes we have a component that has many states that need to be reset to initial values. I stumbled upon this problem today and found it interesting. Consider this simple example below.
1<script>
2export default {
3 data: () => ({
4 items: [], deep: { items: [] }, counter: 0}),
5 methods: {
6 resetState() {
7 //
8 },
9 },
10}
11</script>
12
13<template>
14 <button @click="items.push(items.length + 1); deep.items.push(items.length); counter++;">
15 Add item
16 </button>
17 <button @click="resetState">
18 Reset State
19 </button>
20 <hr />
21 <pre>{{ $data }}</pre>
22</template>
In this case, you can do it manually like this
1...
2methods: {
3 resetState() {
4 this.$data.items = [];
5 this.$data.deep = { items: [] };
6 this.$data.counter=0;
7 }
8}
9...
But what if we retrieve the initial state from a function? Can we still do it like this.$data = this.getInitialState()
? For instance,
1<script>
2const getInitialState = () => ({ items: [], deep: { items: [] }, counter: 0});
3
4export default {
5 data: getInitialState,
6 methods: {
7 resetState() {
8 this.$data = getInitialState();
9 }
10 }
11}
12</script>
13
14<template>
15 ...
16</template>
No, we will this error - proxy set handler returned false for property '"$data"'.
It is not possible due to data being read-only and can not be overwritten. We can instead do it like this
1<script>
2const getInitialState = () => ({ items: [], deep: { items: [] }, counter: 0});
3
4export default {
5 data: getInitialState,
6 methods: {
7 resetState() {
8 Object.assign(this.$data, getInitialState()});
9 }
10 }
11}
12</script>
13
14<template>
15 ...
16</template>
Object.assign
will copy all values returned from getInitialState
into the data
object. And if we don't want to overwrite all states e.g. counter, we can do it like this
1<script>
2const getInitialState = () => ({ items: [], deep: { items: [] }, counter: 0});
3
4export default {
5 data: getInitialState,
6 methods: {
7 resetState() {
8 const counter = this.$data.counter;
9 Object.assign(this.$data, {...getInitialState(), counter});
10 }
11 }
12}
13</script>
14
15<template>
16 <button @click="items.push(items.length + 1); deep.items.push(items.length); counter++;">
17 Add item
18 </button>
19 <button @click="resetState">
20 Reset State
21 </button>
22 <hr />
23 <pre>{{ $data }}</pre>
24</template>