Svelte 5 методов реактивного хранилища

Приведенный ниже код работает так, как должен, я просто пытаюсь лучше понять, почему.

Насколько getCurrentElementметод TestState реактивен без использования $derived()? Являются ли методы хранилища, использующие состояние, реактивными по умолчанию?

Я использую [email protected]

test-store.svelte.ts

import { getContext, setContext } from 'svelte';

class TestState {
  elements = [
    {
      id: 'hghxt',
      name: 'Give',
    },
    {
      id: 'vhtl9',
      name: 'Connection',
    },
    {
      id: '5n0t0',
      name: 'Take notice',
    },
    {
      id: 'xlfba',
      name: 'Keep learning',
    },
    {
      id: '1f3z2',
      name: 'Be active',
    },
  ];

  #currentElementId = $state<string>();
  
  getCurrentElement() {
    return this.elements.find(element => element.id === this.#currentElementId);
  }

  setCurrentElement(id: string) {
    if (!this.elements.some(element => element.id === id)) return;

    this.#currentElementId = id;
  }
}

const TEST_STORE_KEY = Symbol('TEST_STORE');

export function setTestState() {
  return setContext(TEST_STORE_KEY, new TestState());
}

export function getTestState() {
  return getContext<ReturnType<typeof setTestState>>(TEST_STORE_KEY);
}

TestComponent.svelte

<script lang = "ts">
  import { getTestState } from '$lib/stores/test-store.svelte';

  // initialised at +page.svelte
  const testState = getTestState();
</script>

{#each testState.elements as { name, id }}
  <button 
    class:bg-yellow = {testState.getCurrentElement()?.id === id} 
    onclick = {() => testState.setCurrentElement(id)}>
    {name}
  </button>
{/each}

🤔 А знаете ли вы, что...
JavaScript поддерживает модульную структуру, что способствует организации кода на больших проектах.


50
1

Ответ:

Решено

В своем «HTML-коде» вы называете testState.getCurrentElement(). Когда вы это сделаете, Svelte заметит, от каких реактивных переменных зависит этот вызов. В getCurrentElement() вы получаете доступ к this.#currentElementId, поэтому Svelte знает, что эту часть «HTML-кода» необходимо повторно отобразить/обновить, когда this.#currentElementId присвоено новое значение.

Вам нужно использовать $derived() только тогда, когда вы хотите автоматически вычислить новое значение, как только реактивная переменная изменит значение, и здесь это не тот случай, поэтому я не вижу здесь никакого смысла использовать $derived().


@JackTempleman, возможно, мы называем вещи по-разному, но такого понятия, как реактивная функция, не существует, по крайней мере, в моем словаре. У нас есть только реактивные переменные/выражения, которые можно создать с помощью некоторых рун, например $state(). Если одна из ваших функций использует реактивную переменную/выражение, то сама эта функция не является реактивной; это просто функция, которая использует реактивные переменные/выражения. Только создание такой функции не приведет к самостоятельным пересчетам. Но если вы вызываете/используете такую ​​функцию в некоторых местах, где Svelte отслеживает реактивность (например, в HTML-коде компонента или в некоторых рунах), тогда Svelte узнает о реактивных переменных/выражениях, которые использует функция, и Svelte вызовет функция снова в будущем, когда эти реактивные переменные/выражения изменят значение.