proxy
proxy 跟踪对原始对象和所有嵌套对象的更改,当对象被修改时通知监听器。
import { proxy } from 'valtio'
const state = proxy({ count: 0, text: 'hello' })
从任何地方改变
您可以像对普通 js 对象一样对其进行更改。
setInterval(() => {
++state.count
}, 1000)
优化:noop 和批处理
将属性值设置为相同值的更新将被忽略。订阅者不会收到版本更改的通知。
const state = proxy({ count: 0 })
state.count = 0 // 没有效果
同一事件循环中的多个更改将被批处理在一起。订阅者将收到单个版本更改的通知。
const state = proxy({ count: 0, text: 'hello' })
// 订阅者将在两次更改后收到一次通知
state.count = 1
state.text = 'world'
嵌套代理
代理可以嵌套在其他 proxy 对象中并作为一个整体进行更新。
import { proxy, useSnapshot } from 'valtio'
const personState = proxy({ name: 'Timo', role: 'admin' })
const authState = proxy({ status: 'loggedIn', user: personState })
authState.user.name = 'Nina'
代理中的 Promise
有关更多详细信息,请参阅 async。
import { proxy } from 'valtio'
const bombState = proxy({
explosion: new Promise((resolve) => setTimeout(() => resolve('Boom!'), 3000)),
})
注意事项
如果您将代理重新分配给一个全新的对象,它将停止工作,因为您正在用新的对象引用替换代理对象。
let state = proxy({ user: { name: 'Timo' } })
subscribe(state, () => {
console.log(state.user.name)
})
// 不会通知订阅者
state = { user: { name: 'Nina' } }
// 相反
let state = proxy({ user: { name: 'Timo' } })
subscribe(state, () => {
console.log(state.user.name) // 输出 "Nina"
})
// 会通知订阅者
state.user.name = 'Nina'
并非所有内容都可以被代理。通常,如果它是可序列化的,您就是安全的。类也可以被代理。但要避免特殊对象。
// 这些不会工作 - 对这些对象的更改不会导致更新
// 到未代理的存储状态,请参阅 ref 的文档
const state = proxy({
chart: d3.select('#chart'),
component: React.createElement('div'),
map: new Map(), // 请参阅 proxyMap
storage: localStorage,
})
// 这会工作
class User {
first = null
last = null
constructor(first, last) {
this.first = first
this.last = last
}
greet() {
return `Hi ${this.first}!`
}
get fullName() {
return `${this.first} ${this.last}`
}
}
const state = proxy(new User('Timo', 'Kivinen'))