1. API
  2. derive

derive

create a new proxy derived from others

You can subscribe to some proxies using get to create snapshots used to compute new values.

import { derive } from 'valtio/utils'

// create a base proxy
const state = proxy({
  count: 1,
})

// create a derived proxy
const derived = derive({
  doubled: (get) => get(state).count * 2,
})

// alternatively, attach derived properties to an existing proxy
derive(
  {
    tripled: (get) => get(state).count * 3,
  },
  {
    proxy: state,
  }
)

underive

stop evaluating

In some cases you may want to unsubscribe after deriving a proxy. To do so, use the underive util. You may also pass keys to indicate which properties you want to unsubscribe. If you specify delete option, it will delete the properties and you can attach new derived properties.

import { derive, underive } from 'valtio/utils'
const state = proxy({
  count: 1,
})

const derivedState = derive({
  doubled: (get) => get(state).count * 2,
})

underive(derivedState)

Usage patterns

Re-computes when unrelated properties change

With derive, the computation will occur if any property of the base proxy changes. Example:

const baseProxy = proxy({
  counter1: 0,
  counter2: 0,
  counter3: 0,
  counter4: 0,
})

const countersOneAndTwoSelectors = derive({
  sum: (get) => get(baseProxy).counter1 + get(baseProxy).counter2,
})

In this example even if baseProxy.counter3 or baseProxy.counter4 are changed, countersOneAndTwoSelectors will re-compute all of the keys in it.

get sub-objects due to update of unrelated proxies on parent proxy

As noted on his page, re-computation occurs when unrelated properties change. It is possible to use get on sub-objects. This has the benefit of not re-computing when properties of the parent object are updated. Example:

const baseProxy = proxy({
  counter1And2: {
    counter1: 0,
    counter2: 0,
  },
  counter3: 0,
  counter4: 0,
})

const countersOneAndTwoSelectors = derive({
  sum: (get) =>
    get(baseProxy.counter1And2).counter1 + get(baseProxy.counter1And2).counter2,
})

Now even if counter3 and counter4 are updated, it will not cause re-computation of countersOneAndTwoSelectors.