Magasin d'État

L'avantage de Markup state est le fait qu'il s'agit d'une API autonome qui fonctionne très bien avec le modèle lui-même.

Cela vous permet de gérer l'état partagé/global en dehors du composant et de les injecter directement dans le modèle ou d'effectuer des effets secondaires si nécessaire. Tout cela sans vous soucier des abonnements et des nettoyages.

Créer un magasin d'état

Prenons par exemple ce magasin d'état todos :

typescript
// src/stores/todos.ts

type UUID = `${string}-${string}-${string}-${string}-${string}`

export interface Todo {
    id: UUID
    name: string
    description: string
    status: 'done' | 'pending' | 'removed'
    dateCreated: Date
    dateLastUpdated: Date
}

const [todos, updateTodos] = state<Todo[]>([])

export const todoList = todos

Comme vous pouvez le voir, nous pouvons créer un fichier dédié à la gestion d'un état particulier que nous souhaitons utiliser à plusieurs endroits de notre application.

Consommer l'état du magasin

Nous n'avons pas à nous soucier de l'abonnement pour le rendu de ces données, nous pouvons les injecter directement dans le modèle.

javascript
import {todoList} from "./stores/todos"

const App = () => {

    const renderTodo = () => {...}

    // html will handle all subscribing and
    // unsubscribing from todoList state
    return html`
        <ul id="todos">
            ${repeat(todoList, renderTodo)}
        </ul>
    `
}

Assez simple, pour effectuer quelque chose à chaque fois que cette liste change, nous pouvons simplement utiliser le effect.

javascript
import { todoList } from './stores/todos'

const defaultTodosByStatus = { done: [], pending: [], removed: [] }

const [todosByStatus, updateTodosByStatus] = state(defaultTodosByStatus)

// effect will handle subscribing to the todoList state
const unsubFromEffect = effect(() => {
    updateTodosByStatus(
        todoList().reduce((acc, todo) => {
            if (!acc[todo.status]) {
                acc[todo.status] = []
            }

            acc[todo.status].push(todo)

            return acc
        }, defaultTodosByStatus)
    )
})

// call "unsubFromEffect" to unsubscribe from todoList state

Définir les actions du magasin

Étant donné que le magasin est simplement un fichier, nous pouvons exposer des fonctions qui effectuent des modifications dans les données sans exposer la logique ou la complexité de l'état.

typescript
// src/stores/todos.ts

...

export const createTodo = (name: string) => {
  const dateCreated = new Date();
  const todo: Todo = {
    id: crypto.randomUUID(),
    name,
    description: "",
    status: "pending",
    dateCreated,
    dateLastUpdated: dateCreated
  }

  updateTodos(prev => [...prev, todo])
}

export const updateTodo = (id: UUID, data: Partial<Todo>) => {
    updateTodos(prev => prev.map(todo => {
        if(todo.id === id) {
            return {
                ...todo,
                name: data.name ?? todo.name,
                description: data.description ?? todo.description,
                status: data.status ?? todo.status,
                dateLastUpdated: new Date()
            }
        }

        return todo;
    }))
}

export const deleteTodo = (id: UUID) => {
    updateTodos(prev => prev.filter(todo => {
        return todo.id !== id;
    }))
}

export const clearTodos = () => {
    updateTodos([])
}

Ces actions peuvent être ce que vous voulez. Ils peuvent

Le stockage des données et la gestion de l'état ne doivent pas nécessairement être complexes et il vous suffit d'utiliser les API facilement disponibles dans l'environnement pour faire ce que vous voulez.

Regardez cet exemple de magasin d'état todo avec stockage local.

modifier ce document