A (work-in-progress) generic entity store for Svelte projects.
Check out the full docs for details.
This is ultimately just a custom store built on top of svelte/store. Like the rest of Svelte, the built in stores are excellent building blocks that aim to give you all the tools you need without trying to solve every single scenario out of the box.
The goal with svelte-entity-store
is to provide a simple, generic solution for storing collections of entity objects. Throwing an array of items into a basic writeble
store doesn't scale well if you have a lot of items and need to quickly find or update one item in the store.
npm i -s svelte-entity-store
Check out '/examples' for a working TodoMVC demo based on SvelteKit. More to come!
<script lang="ts">
import { entityStore } from 'svelte-entity-store'
// Define your entity interface
interface TodoItem {
id: string
description: string
completed: boolean
}
// Write a getter function that returns the ID of an entity (can be inlined in the constructor also)
// Currently number and string values are valid IDs
const getId = (todo: TodoItem) => todo.id
// Initialize the store
// (optional) the constructor accepts an Array as a second param
// ex: if you rehydrate state from localstorage
const store = entityStore<TodoItem>(getId)
// Get a derived store for every active todo
const activeTodos = store.get((todo) => todo.completed)
// toggle a todo
function toggle(id: string) {
store.update((todo) => ({ ...todo, completed: !todo.completed }), id)
}
// clear completed todos
function clearCompleted() {
store.remove((todo) => todo.completed)
}
</script>
{#each $activeTodos as todo (todo.id) }
// ... render your UI as usual
{/each}
Gets a derived store to subscribe to one or more entity in the store.
Be careful with how many derived stores you create. It's best to use entityStore.get
at the page or view level and pass state down to dumb components.
i.e. If the TodoMVC app has 10,000 todos in it and each list item is a separate component calling entityStore.get(id)
the performance and memory use will be a nightmare. Just don't do it. You've been warned!
Gets an array with every entity in the store.
Gets the entity by ID, or undefined if it isn't found.
Gets an array of specific entities by ID. IDs will be ignored if they aren't found in the store - the array of entities returned may not be the same length as the ids
array provided.
Gets every entity that matches the predicate - the equivalent of Array.prototype.filter()
Removes one or more entities from the store.
Removes a specific entity by ID, if it exists
Removes one or more entity by ID
Removes every entity that matches the predicate. Note that this removes an entity if the predicate returns true!
Removes all entities, resetting the entity store to it's original default state
Adds or replaces entities in the store. Note that set
will override any old state of an entity if it already existed in the store. Use entityStore.update
if you want to modify the entity instead.
Adds entity to the store, or replaces the old state if it already exists.
Works just like set(entity: T)
, but for each item in the array. This is useful when you ened to update more than one entity and don't want to trigger subscribers until all entities are added.
The subscribe
method for the entire store, see Svelte's docs for more details on the subscribe API.
You really shouldn't need to use this subscribe method unless you're tying the entire store into devtools
or logging.
Updates one or more entity in the store.
This follows the same basic design as writable stores - rather than providing the new entity state you give a callback function that will be given the old entity and returns the new, updated entity.
Runs every entity in the store through the updater
callback. Check out the ('/examples/todomvc')[/examples/todomvc] project, this is used for the "toggle all todos" feature.
Runs a specific entity through the updater callback. updater
will never be called if the entity isn't found in the store.
Runs multiple entities through the updater function. This is useful when you ened to update more than one entity and don't want to trigger subscribers until all entities are updated.
Convenience override in case your code is already using the entire entity, avoids having to do something like update(toggle, todo.id)
.
Works just like update(updater, entities: T[])
, but for each item in the array. This is useful when you ened to update more than one entity and don't want to trigger subscribers until all entities are added.
Runs every entity that matches the predicate through the updater
callback. The predicate works just like Array.prototype.filter
, every entity is run through the predicate and if it returns true the entity is updated.