We’re familiar with React Redux, or Vue’s Vuex, both of which come in packages. For complex state control, there may be specialized libraries like MOBx or RXJS.

State management is still a very useful feature when you want to be able to access a state from anywhere outside of the hierarchy of components, especially when some state needs to be accessed by multiple unrelated components or ordinary JavaScript modules.

Svelte basically divides states into two types, those that can be read and written and those that can only be read. The writable state is the most commonly used state, while the read-only state readable is used to prevent accidental changes.

We can put the code to create the state in a separate file store.js, so that other components that need to use the corresponding state can be introduced and used to facilitate unified management and maintenance.

Writable Stores

// The writable state introduces svelte/store
import { writable } from 'svelte/store';

const count = writable(0); Store 0 is the value stored by store
Copy the code

In Svelte, a store (or state) is just a normal object with a subscribe method,

You can think of an object as a store as long as it implements subscribe correctly

It allows you to automatically push notifications to all subscribe subscribers who subscribe when the value of the store changes.

letCount_value;// count is a store

// subscribe the count_value callback automatically subscribes to count

// This callback is automatically called when the component is initialized and the count value changes to update count_value to the latest count value
count.subscribe(value= > {
  count_value = value;
});
Copy the code
<script>
  import { onDestroy } from 'svelte';
  import { count } from './stores.js';
  import Incrementer from './Incrementer.svelte';
  import Decrementer from './Decrementer.svelte';
  import Reset from './Reset.svelte';

  let count_value;
	
  
 	// subscribe returns a function that is used to unsubscribe
  // Avoid memory leaks when the component is instantiated and destroyed multiple times
  const unsubscribe = count.subscribe(value= > {
    count_value = value;
  });

  onDestroy(unsubscribe);
</script>

<h1>Count is currently {count_value}.</h1>
Copy the code

When a store is a writable store, it means that it has set and update methods in addition to subscribe.

// Update the store value based on the original store value
count.update(n= > n + 1);

// Set the store value to a new value
count.set(0);
Copy the code

Auto-subscriptions

Count. Subscribe is tedious to write and requires manual unsubscription in onDestory.

If you use a lot of stores, the code will look dull and repetitive.

Svelte provides the corresponding syntactic sugar, prefixing the store name with $to refer to the store value.

So Svelte assumes that any identifier beginning with $refers to a store value, and that $is actually a reserved character,

Svelte disallows you to prefix your declared variables with $.

<script>
  import { count } from './stores.js';
</script>

<h1>The current value of count is {$count}</h1>
Copy the code

Read-only state (Readable Stores)

Not all stores allow anyone to write.

There may be a store that stores user information or tokens that need to be sent to the server for access tokens, etc. Changing this value is meaningless.

Readable has two parameters
// Parameter 1: the initial value of store. If not, it can be set to null or undefined

This callback takes a set callback to set the value and returns a stop function.
// The start function is called when the store is read by the first subscriber
// The stop function is called when the last subscriber unsubscribes.

The second parameter can be omitted if the store does not need to be updated internally
export const time = readable(new Date(), function start(set) {
  // Every 1s, change time to the current time, meaning that the read-only store is not immutable
  // If you want to change the value of read-only store, you can only do it through a predefined callback
  // A variable subscribed externally to a store value cannot modify the read-only store value from 'externally'
  const interval = setInterval(() = > set(new Date()), 1000);

  return function stop() { clearInterval(interval); };
});
Copy the code

State Inheritance (Derived Stores)

You can call Derived to create a new store that inherits from one or more other stores

<script>
	import {writable, derived} from 'svelte/store';
	
	// Define a modifiable store
	let num = writable(0)
	
	// Double is derived from num, and when num changes it automatically gets a new value according to preset rules
  // The store for the dispatch process is a readable Store
	let double = derived(
		num, $num = $num
		$num => $num * 2
	)
	
	setInterval(() = > $num+=1.1000)
</script>

<h1>num = {$num}</h1>
<h1>double = {$double}</h1>
Copy the code
<script>
	import {writable, derived} from 'svelte/store';
	
	let num1 = writable(0)
	let num2 = writable(2)
	
  // Can be derived from multiple stores to a single store
	let sum = derived(
		[num1, num2], // Multiple stores are passed in as arrays
		$nums => $nums[0] + $nums[1])setInterval(() = > {
		$num1 += 1
		$num2 *= 2
	}, 1000)
</script>

<h1>num1 = {$num1}</h1>
<h1>num2 = {$num2}</h1>
<h1>sum = {$sum}</h1>
Copy the code

Custom States (Custom Stores)

In daily development, it is common to write states to separate JS files, such as one JS file per state

Encapsulate operations related to a state and export them uniformly to avoid exposing the SET and UPDATE methods and the corresponding update logic

Custom state gives us the opportunity to encapsulate a state that is closer to the business and easier to use

function createCount() {
  const { subscribe, set, update } = writable(0);

  return {
    subscribe,
    increment: () = > update(n= > n + 1),
    decrement: () = > update(n= > n - 1),
    reset: () = > set(0)}; }Copy the code

State Bindings

In Svelte, the binding and use of state in templates is not much different from regular data

<input bind:value={$name}>

<button on:click="{() => $name += '! '}">
  Add exclamation mark!
</button>
Copy the code