/
Вопросы и ответы
/
JavaScript
/

Как перейти с on-change на Valtio в ванильном JS

Как перейти с on-change на Valtio в ванильном JS

месяц назад

Nikolai Gagarinov

Ответы

0

Мы заменяем on-change на valtio/vanilla, чтобы подписываться на изменения состояния и обновлять UI.

Ссылки

Почему Valtio

  • proxy делает состояние реактивным без ручного вызова рендера.
  • subscribe позволяет слушать изменения нужных частей состояния.
  • Можно продолжать мутировать объект напрямую (как и раньше).

Минимальный пример

До (on-change):

import onChange from 'on-change'

const state = {
  count: 0,
}

const watchedState = onChange(state, (path) => {
  if (path === 'count') {
    console.log('count:', state.count)
  }
})

watchedState.count += 1

После (Valtio):

import { proxy, subscribe, snapshot } from 'valtio/vanilla'

const state = proxy({
  count: 0,
})

subscribe(state, () => {
  const snap = snapshot(state)
  console.log('count:', snap.count)
})

state.count += 1

Подписка на кусок состояния

Если нужно реагировать только на часть состояния:

import { proxy, subscribe, snapshot } from 'valtio/vanilla'

const state = proxy({
  form: {
    valid: false,
    error: null,
  },
})

subscribe(state.form, () => {
  const snap = snapshot(state)
  console.log('form.valid:', snap.form.valid)
})

state.form.valid = true

Важно: подписка на state.form работает, только если вы меняете поля, а не заменяете весь объект form.

Не заменяйте вложенные объекты целиком

Так делать не стоит, если вы подписываетесь на вложенный объект:

// плохо: заменяется весь form
state.form = { ...state.form, valid: true }

Лучше так:

// хорошо: меняются поля
state.form.valid = true
state.form.error = null

Если вы все-таки хотите заменять объект целиком, нужно подписываться на корневой объект:

import { subscribeKey } from 'valtio/vanilla/utils'

subscribeKey(state, 'form', () => {
  const snap = snapshot(state)
  console.log('form changed:', snap.form)
})

Особенность Set

Обычный Set не реактивен. Для него есть proxySet:

import { proxySet } from 'valtio/vanilla/utils'

const seenPosts = proxySet()
seenPosts.add('id-1')

Короткий пример из RSS Reader

Подписка в модуле View:

import { proxy, subscribe, snapshot } from 'valtio/vanilla'

const watchedState = proxy(initState)

const renderForm = () => {
  const { form } = snapshot(watchedState)
  // обновление формы
}

subscribe(watchedState.form, renderForm)

Изменения в модели:

watchedState.form.valid = true
watchedState.form.error = null

Итог

  • on-change заменяем на valtio/vanilla.
  • Состояние — через proxy.
  • Обновления UI — через subscribe и snapshot.
  • Вложенные объекты мутируем по полям.
  • Для Set используем proxySet.

месяц назад

Nikolai Gagarinov

+7 800 100 22 47

бесплатно по РФ

+7 495 085 21 62

бесплатно по Москве

108813 г. Москва, вн.тер.г. поселение Московский,
г. Московский, ул. Солнечная, д. 3А, стр. 1, помещ. 20Б/3
ОГРН 1217300010476
ИНН 7325174845