Valtio
Micro State Management
NIYA PANAMDANAM
Twitter: @findniya
Website: findniya.com
About me
- Live in Toronto
- Frontend Tech Lead: Architect
- Work for a Healthie, a Telehealth platform based out of New York.
- Coffee addict
- anime/ manga nerd
What is valtio
Proxy Based
Uses native Javascript proxy to create observable state objects.
Immutable State
Allows immutable state updates. When state changes are made, new state objects are created rather than modifying the existing ones.
Minimal Boilerplate
Very little boilerplate to setup and update state.
Javascript Proxy
- Introduced in ES6
- Is an object that wraps another object or function and intercepts its fundamental operations, such as property access, assignment, invocation, and more.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
Javascript Proxy
- Introduced in ES6
- Is an object that wraps another object or function and intercepts its fundamental operations, such as property access, assignment, invocation, and more.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
const target = {
message1: "hello",
message2: "everyone",
};
const handler2 = {
get(target, prop, receiver) {
if (prop === "message2") {
return "world";
}
return Reflect.get(...arguments);
},
};
const proxy = new Proxy(target, handler2);
console.log(proxy.message1); // hello
console.log(proxy.message2); // world
const target = {
message1: "hello",
message2: "everyone",
};
const handler2 = {
get(target, prop, receiver) {
if (prop === "message2") {
return "world";
}
return Reflect.get(...arguments);
},
};
const proxy = new Proxy(target, handler2);
console.log(proxy.message1); // hello
console.log(proxy.message2); // world
Valtio can be used in vanilla Javascript.
This also means we can use Valtio states in older React Class components.
Why this Matters
import { proxy, snapshot } from 'valtio'
const store = proxy({ name: 'Mika' })
const snap1 = snapshot(store) // an efficient copy of the current store values, unproxied
const snap2 = snapshot(store)
console.log(snap1 === snap2) // true, no need to re-render
store.name = 'Hanna'
const snap3 = snapshot(store)
console.log(snap1 === snap3) // false, should re-render
- You can make changes to it in the same way you would to a normal js-object.
- Proxy tracks changes to the object and all nested proxy objects.
- Multiple changes are batched and changes with the same value are not recorded.
React Implementation
import { proxy } from 'valtio'
const personState = proxy({
name: 'Timo',
role: 'admin'
})
const authState = proxy({
status: 'loggedIn',
user: personState
})
console.log(authState.user.name) // would return Timo
authState.user.name = 'Nina'
console.log(authState.user.name) // would return Nina
-
useSnapshot
creates a local snapshot of the state that triggers a re-render of the component on the key change. - It wraps the Valtio snapshot in an access-tracking proxy to make sure the component or child component only re-renders on the specific key change.
Read State With snapshots
import { proxy, useSnapshot } from 'valtio'
const personState = proxy({
name: 'Timo',
role: 'admin'
})
const authState = proxy({
status: 'loggedIn',
user: personState
})
function UserProfile() {
const snap = useSnapshot(authState.user)
return (
<div>
{snap.name}
</div>
)
}
Look Out!
Don't re-assign the proxy to a whole new object.
Then state will stop working as expected.
let state = proxy({
user: {
name: 'Timo'
}
})
subscribe(state, () => {
console.log(state.user.name)
})
// will not notify subscribers
state = {
user: {
name: 'Nina'
}
}
// DON'T DO THIS
Instead
Mutate the object.
let state = proxy({
user: {
name: 'Timo'
}
})
subscribe(state, () => {
console.log(state.user.name)
})
state.user.name = 'Nina'
1 more cool thing
It works with Redux Dev tool!!
import { devtools } from 'valtio/utils'
const state = proxy({
count: 0,
text: 'hello'
})
const unsub = devtools(state, {
name: 'state name',
enabled: true
})
Read More
Valtio
By Niya Panamdanam
Valtio
- 161