Nick Jennings
Nick Jennings

Reputation: 4044

Unable to reset store values

I would like to reset an existing store's values to the defaults. For UX reasons, I don't want to create a new store.

const defaults = {
  name: {
    value: "",
  },
  foo: [],
  some: {
    other: {
      data: ""
    }
  }
};
const store = writable(defaults);

export const myStore = {
  subscribe: store.subscribe,
  reset: () => {
    store.set(defaults);
  }
};

The store behaves as expected, with the exception of the reset() method. Whenever it's called it does not update the store, none of the reactive bindings reflect what should be the default values.

...
$myStore.name.value = "foo";
// foo
myStore.reset();
$myStore.name.value;
// foo

Upvotes: 1

Views: 969

Answers (2)

k4mars
k4mars

Reputation: 11

Another way -

const defaults = {
  name: {
    value: "",
  },
  foo: [],
  some: {
    other: {
      data: ""
    }
  }
};
const store = writable(defaults);

export const myStore = {
  subscribe: store.subscribe,
  reset: () => {
    store.set(JSON.parse(JSON.stringify(defaults)));
  }
};

Upvotes: 0

Gabriel d'Agosto
Gabriel d'Agosto

Reputation: 494

This isn't an issue with Svelte, but with how javascript handles objects. When you assign an object to another variable, it will only assign a reference, and not clone the object. This means that, when you call $myStore.name.value = "foo";, you are actually updating the same object that is stored in defaults.

You can observe this by running the code below

let a = {name: ''};
let b = a;
b.name = 'test';
console.log(a); // {name: 'test'}

Since you're using objects inside objects, just destructuring default also won't work, since you'll only get a shallow copy of an object, meaning that you could update $myStore.name but wouldn't be able to update $myStore.name.value properly.

To properly copy defaults, you could use structuredClone, which is available in Chrome 98, Firefox 94 and Node 17. Rewriting your code, it would be something like this:

const store = writable(structuredClone(defaults));

export const myStore = {
  subscribe: store.subscribe,
  reset: () => {
    store.set(structuredClone(defaults));
  }
};

Upvotes: 2

Related Questions