创建一个 store
创建一个 store 使用的是 Valtio 中提供的 proxy
函数。这个函数接受一个普通的对象作为参数,并返回一个代理对象。这个代理对象可以像普通对象一样被读取和修改,但所有的修改都会被自动跟踪。
以下是一个最简单的 store 示例。
import { proxy } from "valtio";
const store = proxy({
count: 0,
});
甚至可以创建一个嵌套的 store。
const personStore = proxy({ name: "John", role: "user" });
const authenticationStore = proxy({ status: "logged-in", user: personStore });
注意在使用 proxy
创建 store 的时候不是什么内容都可以被代理的,通常可以被序列化的类型都可以被代理,比如字符串、数字、布尔值、数组、对象等。例如以下内容就不能被代理,因为其中的内容是无法被序列化的。
const unableProxied = proxy({
chart: d3.select("#chart"),
component: React.createElement("div"),
map: new Map(),
storage: localStorage,
});
Valtio 在创建一个对象的代理的时候,会自动将其中嵌套的列表、对象等也都进行代理。所以上面嵌套定义的 store 甚至可以简化成以下形式。
const authenticationStore = proxy({
status: "logged-in",
user: { name: 'John', role: "user },
});
在被代理对象中声明无需代理的属性
Valtio 虽然可以自动代理一个对象中的所有嵌套内容,但是也提供了一种方式来声明一些属性不需要被代理。这可以通过在定义 store 的时候,使用 ref
来实现。例如:
import { proxy, ref } from "valtio";
const store = proxy({
page: 1,
total: 0,
books: ref([]),
});
在这个例子中,books
属性被使用 ref
包装了,这意味着 books
属性不会被自动代理。相反,它将作为一个普通的 JavaScript 数组来处理。例如现在调用 store.books.push({ id: 1, title: "Book 1" })
是不会触发任何更新的。但是需要注意的是,如果对 books
重新赋值是不可以的,这会破坏 ref
的作用,例如 store.books = []
。