Here the REPL: /repl/56770fec88af4b76bdc8ea962178854e?version=3.42.1
Here the code:
App.svelte:
<script>
import {editableStore} from "./store";
let name = "John"
$: player = editableStore(name);
</script>
<h1>Hello {$player.name}!</h1>
<button on:click={() => name = (name === "Bob" ? "Jerry" : "Bob")}>
Change name
</button>
<h2>Log:</h2>
{#each $player.log as log}
<li>{log}</li>
{/each}
store.js:
import {writable} from "svelte/store";
const defaultStore = {
name: "Bob",
age: 18,
log: []
};
export const editableStore = (name) => {
console.log("Recreated with name:", name);
const {subscribe, update} = writable({...defaultStore}, () => () => clearInterval);
if (name) {
update(s => ({...s, name}));
}
const clearInterval = setInterval(() => {
update(s => ({...s, log: [...s.log, new Date()]}))
}, 1000)
return { subscribe };
};
As you can see if you click on "Change name" the store gets recreated.
This is what I need to avoid.
But how?
Here the REPL: https://svelte.dev/repl/56770fec88af4b76bdc8ea962178854e?version=3.42.1
Here the code:
App.svelte:
<script>
import {editableStore} from "./store";
let name = "John"
$: player = editableStore(name);
</script>
<h1>Hello {$player.name}!</h1>
<button on:click={() => name = (name === "Bob" ? "Jerry" : "Bob")}>
Change name
</button>
<h2>Log:</h2>
{#each $player.log as log}
<li>{log}</li>
{/each}
store.js:
import {writable} from "svelte/store";
const defaultStore = {
name: "Bob",
age: 18,
log: []
};
export const editableStore = (name) => {
console.log("Recreated with name:", name);
const {subscribe, update} = writable({...defaultStore}, () => () => clearInterval);
if (name) {
update(s => ({...s, name}));
}
const clearInterval = setInterval(() => {
update(s => ({...s, log: [...s.log, new Date()]}))
}, 1000)
return { subscribe };
};
As you can see if you click on "Change name" the store gets recreated.
This is what I need to avoid.
But how?
Share Improve this question edited Aug 13, 2021 at 14:51 Fred Hors asked Aug 13, 2021 at 14:31 Fred HorsFred Hors 4,0753 gold badges39 silver badges108 bronze badges 1- 1 You should follow the Svelte store tutorial: svelte.dev/tutorial/writable-stores – Riddell Commented Aug 13, 2021 at 15:18
2 Answers
Reset to default 7Instead of re-creating the store every time name
changes, only create it once and set $player.name
when name
changes.
<script>
import {editableStore} from "./store";
let name = "John";
let player = editableStore(name);
$: $player.name = name;
</script>
This will require you to update your store method to return the set
function.
export const editableStore = (name) => {
console.log("Recreated with name:", name);
// also destructure set here
const {subscribe, update, set} = writable({...defaultStore}, () => () => clearInterval);
if (name) {
update(s => ({...s, name}));
}
const clearInterval = setInterval(() => {
update(s => ({...s, log: [...s.log, new Date()]}))
}, 1000)
// also return set here
return { subscribe, set };
};
Try to instanciate your store as son as possible like in the ./store.js
file and then use the set
or update
method instead of instanciate it in the ponent directly:
// store.js
import {writable} from "svelte/store";
const defaultStore = {
name: "Bob",
age: 18,
log: []
};
export const createEditableStore = () => {
const {subscribe, update, set} = writable({...defaultStore}, () => () => clearInterval);
const clearInterval = setInterval(() => {
update(s => ({...s, log: [...s.log, new Date()]}))
}, 1000)
return { subscribe, set, update };
};
export const player = createEditableStore()
<!-- App.svelte -->
<script>
import { player } from "./store";
let name = "John"
$: player.update(p => ({ ...p, name }))
</script>
<h1>Hello {$player.name}!</h1>
<button on:click={() => name = (name === "Bob" ? "Jerry" : "Bob")}>
Change name
</button>
<h2>Log:</h2>
{#each $player.log as log}
<li>{log}</li>
{/each}
Have a look at the REPL.