Как обновить этот стройный магазин, не создавая его каждый раз заново?

#javascript #svelte #svelte-3 #svelte-component #svelte-store

Вопрос:

Вот РЕПЛ: https://svelte.dev/repl/56770fec88af4b76bdc8ea962178854e?version=3.42.1

Вот код:

Приложение.стройная:

 <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 };
};
 

Как вы можете видеть, если вы нажмете «Изменить имя», магазин будет воссоздан заново.

Это то, чего мне нужно избегать.

Но как?

Комментарии:

1. Вы должны следовать руководству по магазину Svelte: svelte.dev/учебник/доступные для записи-магазины

Ответ №1:

Вместо того, чтобы воссоздавать магазин каждый раз name , когда он меняется, создайте его только один раз и установите $player.name время name изменения.

 <script>
    import {editableStore} from "./store";
    
    let name = "John";

    let player = editableStore(name);
    $: $player.name = name;
</script>
 

Для этого потребуется обновить метод хранилища, чтобы вернуть set функцию.

 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 };
};
 

Ответ №2:

Попробуйте создать экземпляр вашего хранилища как можно быстрее, как в ./store.js файле, а затем используйте метод set или update вместо того, чтобы создавать его непосредственно в компоненте:

 // 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}
 

Взгляните на РЕПЛ.