I've followed along with the great Svelte tutorial but I'm having trouble understanding when I should use derived in my custom stores. In this example, I'm creating a game with 3 states:
PRE_GAMEIN_GAMEPOST_GAMEI want to return a boolean check for when I'm in one of those states, and I think it would be best on the custom store itself.
This is my current code:
import { writable, derived } from 'svelte/store';
export const gamestate = (() {
  const { set, subscribe } = writable('PRE_GAME');
  return {
    subscribe,
    set
  };
})();
export const preGame = derived(gamestate, ($gamestate) => $gamestate === 'PRE_GAME');
export const inGame = derived(gamestate, ($gamestate) => $gamestate === 'IN_GAME');
export const postGame = derived(gamestate, ($gamestate) => $gamestate === 'POST_GAME');
Is it possible to move the derived methods onto the gamestate store like gamestate.preGame()? Does that make sense to do in Svelte? Then I can call $gameState and get whichever value, but also return a boolean check when I need an explicit value.
I expected to be able to do check the internal value without needing to derive its value. Maybe something like below, but it always returns false because gamestate is a writable object.
export const createStore = (() {
  const { set, subscribe } = writable('PRE_GAME');
  return {
    subscribe,
    set,
    preGame: () => gamestate === 'PRE_GAME',
    inGame: () => gamestate === 'IN_GAME',
    postGame: () => gamestate === 'POST_GAME',
  };
})();
What am I misunderstanding here?
What you do is return a subscription to a derived store in your custom store:
import { derived, writable } from 'svelte/store'
export const gameState = (() => {
  const store = writable('PRE_GAME')
  const store2 = derived(store, $store => ({
    preGame: $store === 'PRE_GAME',
    inGame: $store === 'IN_GAME',
    postGame: $store === 'POST_GAME'        
  }))
    
  return {
    set: store.set,
    subscribe: store2.subscribe
  }
})()
Now when you do set on the store it will set the value on store, then store2 will derive new values and the subscribers will react to those changes:
<script>
  import { gameState } from "./store.js"
</script>
<button on:click="{() => $gameState='PRE_GAME'}">go PRE_GAME</button>
<button on:click="{() => $gameState='IN_GAME'}">go IN_GAME</button>
<button on:click="{() => $gameState='POST_GAME'}">go POST_GAME</button>
<br />
{#if $gameState.preGame}
    <span>PRE_GAME</span>
{/if}
{#if $gameState.inGame}
    <span>IN_GAME</span>
{/if}
{#if $gameState.postGame}
    <span>POST_GAME</span>
{/if}
You can also define different getters for each specific state:
import { derived, writable } from 'svelte/store'
export const gameState = (() => {
  const store = writable('PRE_GAME')
    const { set, subscribe } = store
  return {
    set,
    subscribe,
        get preGame() { return derived(store, $store => $store === 'PRE_GAME') },
        get inGame() { return derived(store, $store => $store === 'IN_GAME') },
        get postGame() { return derived(store, $store=> $store === 'POST_GAME') },
  }
})()
Now the only problem is that doing $gameState.preGame does not exists because that tries to get the preGame prop from the content of $gameState, and doing gameState.$preGame or similar is invalid syntax.  To get around that you can destructure the props out of the store where you need them:
<script>
  import { gameState } from './store.js'
  const { preGame, inGame, postGame } = gameState
</script>
<span>Current State: {$gameState}</span>
{#if preGame}<span>PRE_GAME</span>{/if}
{#if inGame}<span>IN_GAME</span>{/if}
{#if postGame}<span>POST_GAME</span>{/if}
                        Custom methods on the stores are for how you mutate the state (set and update), but stores generally are only have one getter: the state. And I don't think you want it to be otherwise.
From here on, I see three solutions :
{ gameSate: 'PRE_GAME', isPreGame: true, isInGame: false, isPostGame: false } and then use a custom update function.get()).I would decide between just by pure DRYness: imports vs. repeating the clause.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With