Giter VIP home page Giter VIP logo

valtio's Introduction

valtio



npm i valtio makes proxy-state simple

Build Status Build Size Version Downloads Discord Shield

Wrap your state object

Valtio turns the object you pass it into a self-aware proxy.

import { proxy, useProxy } from 'valtio'

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

Mutate from anywhere

You can make changes to it in the same way you would to a normal js-object.

setInterval(() => {
  ++state.count
}, 1000)

React via useProxy

Create a local snapshot that catches changes. Rule of thumb: read from snapshots, mutate the source. The component will only re-render when the parts of the state you access have changed, it is render-optimized.

function Counter() {
  const snapshot = useProxy(state)
  return (
    <div>
      {snapshot.count}
      <button onClick={() => ++state.count}>+1</button>
    </div>
  )
}

Subscribe from anywhere

You can access state outside of your components and subscribe to changes.

import { subscribe } from 'valtio'

// Suscribe to all state changes
const unsubscribe = subscribe(state, () => console.log('state has changed to', state))
// Unsubscribe by calling the result
unsubscribe()

You can also subscribe to a portion of state.

const state = proxy({ obj: { foo: 'bar' }, arr: ['hello'] })

subscribe(state.obj, () => console.log('state.obj has changed to', state.obj))
state.obj.foo = 'baz'

subscribe(state.arr, () => console.log('state.arr has changed to', state.arr))
state.arr.push('world')

To subscribe to a primitive value of state, consider subscribeKey in utils.

Suspend your components

Valtio supports React-suspense and will throw promises that you access within a components render function. This eliminates all the async back-and-forth, you can access your data directly while the parent is responsible for fallback state and error handling.

const state = proxy({ post: fetch(url).then((res) => res.json()) })

function Post() {
  const snapshot = useProxy(state)
  return <div>{snapshot.post.title}</div>
}

function App() {
  return (
    <Suspense fallback={<span>waiting...</span>}>
      <Post />
    </Suspense>
  )
}

Avoid state properties to be wrapped with proxies

See pmndrs#62 for more information.

import { proxy, ref } from 'valtio'

const state = proxy({
  count: 0,
  dom: ref(document.body),
})

Update transiently

You can subscribe a component to state without causing render, just stick the subscribe function into useEffect.

function Foo() {
  const ref = useRef(state.obj)
  useEffect(() => subscribe(state.obj, () => ref.current = state.obj), [state.obj])
  // ...

Update synchronously

By default, state mutations are batched before triggering re-render. Sometimes, we want to disable the batching.

function TextBox() {
  const snapshot = useProxy(state, { sync: true })
  return <input value={snapshot.text} onChange={(e) => (state.text = e.target.value)} />
}

Dev tools

You can use Redux DevTools Extension for plain objects and arrays.

import { devtools } from 'valtio/utils'

const state = proxy({ count: 0, text: 'hello' })
const unsub = devtools(state, 'state name')

Use it vanilla

Valtio is not tied to React, you can use it in vanilla-js.

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

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

subscribe(state, () => {
  console.log('state is mutated')
  const obj = snapshot(state) // A snapshot is an immutable object
})

Use it locally in components

You can use it locally in components. Notes

import { useLocalProxy } from 'valtio/utils'

function Foo() {
  const [snapshot, state] = useLocalProxy({ count: 0, text: 'hello' })

Proxy with computed

You can have computed values with dependency tracking. This is for experts. Notes

import { proxyWithComputed } from 'valtio/utils'

const state = proxyWithComputed({
  count: 1,
}, {
  doubled: snap => snap.count * 2
})

// Computed values accept custom setters too:
const state2 = proxyWithComputed({
  firstName: 'Alec',
  lastName: 'Baldwin'
}, {
  fullName: {
    get: (snap) => snap.firstName + ' ' + snap.lastName,
    set: (state, newValue) => { [state.firstName, state.lastName] = newValue.split(' ') },
})

// if you want a computed value to derive from another computed, you must declare the dependency first:
const state = proxyWithComputed({
  count: 1,
}, {
  doubled: snap => snap.count * 2,
  quadrupled: snap => snap.doubled * 2
})

valtio's People

Contributors

dai-shi avatar drcmda avatar thelinuxlich avatar aslemammad avatar iinfin avatar a-eid avatar a-type avatar jherr avatar jon301 avatar kitten avatar steve8708 avatar theomjones avatar zvictor avatar yesmeck avatar wilcoschoneveld avatar c0d3t3k avatar tsumo avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.