Zssaer
Zssaer

Reputation: 233

how to reset one of data in pinia state?

I have a design in setting page,every one of them hava reset button, now i using pinia to be store library. I kown $reset is reset the whole pinia state,so,how to reset one of data in pinia state?

Upvotes: 11

Views: 17584

Answers (2)

tao
tao

Reputation: 90068

The typical way I do this:

const defaultState = {
  foo: 'bar'
}

export const useFoo = defineStore('foo', {
  state: () => ({ ...defaultState }),
  actions: {
    reset() {
      Object.assign(this, defaultState);
    }
  }
})

You get the initial state and a reset() action which resets whatever state has to the initial. Obviously, you can pick and choose what you put in defaultState.


If you only want to reset one particular state prop, without touching anything else, just assign the default value to it:

useFoo().foo = 'bar';

If you find it useful, you can also have a generic update, where you can assign multiple values to state in one call:

actions: {
  update(payload) {
    Object.assign(this, payload)
  }
}

Use it like:

useFoo().update({ 
  foo: 'bar',
  // add more props if needed...
});

Last, but not least, lodash's pick can be used to pick and choose what gets reset, from the defaultState values, without having to specify the actual values:

import { pick } from 'lodash-es';

const defaultState = {
  foo: 'bar',
  boo: 'far'
};

export const useFoo = defineStore('foo', {
  state: () => ({ ...defaultState }),
  actions: {
    reset(keys) {
      Object.assign(this, keys?.length
        ? pick(defaultState, keys)
        : defaultState // if no keys provided, reset all
      );
    }
  }
})

use it like:

useFoo().reset(['foo']);

This only resets foo to 'bar', but doesn't touch current value of boo.

To reset both (using the action above):

useFoo().reset(['foo', 'boo']);

...or useFoo().reset() or useFoo().reset([]), both of which reset all the state, because the keys?.length condition is falsey.

Here's a working example:

const { createPinia, defineStore, storeToRefs } = Pinia;
const { createApp, reactive, toRefs } = Vue;
const defaultState = {
  foo: "bar",
  boo: "far",
};

const useStore = defineStore("foobar", {
  state: () => ({ ...defaultState }),
  actions: {
    reset(keys) {
      Object.assign(
        this,
        keys?.length ? _.pick(defaultState, keys) : defaultState
      );
    },
  },
});

const pinia = createPinia();
const app = createApp({
  setup() {
    const store = useStore();
    const localState = reactive({
      resetFoo: false,
      resetBoo: false,
    });
    const resetStore = () => store.reset(
      [
        localState.resetFoo ? "foo" : null,
        localState.resetBoo ? "boo" : null,
      ].filter((o) => o)
    );
    return { ...storeToRefs(store), ...toRefs(localState), resetStore };
  },
});
app.use(pinia);
app.mount("#app");
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<script src="https://unpkg.com/vue-demi"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pinia/2.0.28/pinia.iife.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
<div id="app">
  <input v-model="foo" />
  <input v-model="boo" />
  <pre v-text="JSON.stringify({foo, boo}, null, 2)"></pre>
  <hr>
  <label>
    <input type="checkbox" v-model="resetFoo" />ResetFoo</label>
  <label>
    <input type="checkbox" v-model="resetBoo" />ResetBoo</label>
  <button @click="resetStore">Reset</button>
  
</div>

Upvotes: 11

Whitespacecode
Whitespacecode

Reputation: 1378

Above example doesn't reset one property to the default value when the property is already changed. That's because the defaultState is reactive, you need to copy the defaultState so it's not reactive anymore.

import _pick from 'lodash.pick';

const defaultState = {
  foo: 'bar',
};

export const useStore = defineStore('store', {
  state: () => ({...defaultState}),
  actions: {
    reset(keys) {
      Object.assign(this, keys?.length
        ? _pick(defaultState, keys)
        : defaultState // if no keys provided, reset all
      );
    }
  }
})

Use it like this

useStore().reset(['foo']);

This will now reset foo back to bar

Upvotes: 4

Related Questions