docs/docs/docs/max/valtio.md
@umijs/max 内置了 valtio 数据流方案。
配置开启。
export default {
valtio: {},
}
极其简单。
import { proxy, useSnapshot } from 'umi';
// 1、定义数据
const state = proxy({ count: 0 });
// 2、使用数据
const snap = useSnapshot(state);
snap.count;
// 3、更新数据
state.count += 1;
天然支持。
import { proxy } from 'umi';
const state = proxy({ count: 0 });
state.count;
state.count += 1;
import { proxyWithComputed } from 'umi';
const state = proxyWithComputed({
count: 0,
}, {
double: snap => snap.count * 2,
});
两种用法,可以和 state 放一起,也可以分开。
import { proxy } from 'umi';
// 方法一:放一起
const state = proxy({
count: 0,
actions: {
add() {
// 注意这里别用 this.count,基于 snap 调用时会报错
state.count += 1;
},
}
});
// 方法二:分开放
const state = proxy({ count: 0 });
const actions = {
add() {
state.count += 1;
},
// 异步 action
async addAsync() {
state.count += await fetch('/api/add');
},
};
import { proxy } from 'umi';
// 比如如下定义
// state.foo 和 state.bar 都是 proxy,可拆分使用
const state = proxy({
foo: { a: 1 },
bar: { b: 1 },
});
// 组合
const foo = proxy({ a: 1 });
const bar = proxy({ b: 1 });
const state = proxy({ foo, bar });
如果 props 内容和 state 无关,可以不处理;如果有关,按以下方式用 context 包一下,同时做 props 到 state 的数据同步即可。
import { proxy } from 'umi';
// 1、createContext
const MyContext = createContext();
// 2、Provider
const value = useRef(proxy({ count: 0 })).current;
<MyContext.Provider value={value} />
// 3、useContext
useContext(MyContext);
import { proxy, proxyWithDevtools } from 'umi';
const state = proxy({ count: 0 });
proxyWithDevtools(state, { name: 'count', enabled: true });
import { proxyWithHistory } from 'umi';
const state = proxyWithHistory({
count: 0,
});
state.value.count;
state.value.count += 1;
state.undo();
state.redo();
state.history;
待实现。
import { proxyWithPersistant } from 'umi';
const state = proxyWithPersistant({
count: 0,
}, {
type: 'localStorage',
key: 'count',
});
valtio 是基于组装式的扩展方式,相比 middleware 的方式在类型提示上会更好一些。比如我要实现前面的 proxyWithPersistant,简单点的方案只要这样,
export function proxyWithPersist<V>(val: V, opts: {
key: string;
}) {
const local = localStorage.getItem(opts.key);
const state = proxy(local ? JSON.parse(local) : val);
subscribe(state, () => {
localStorage.setItem(opts.key, JSON.stringify(snapshot(state)));
});
return state;
}
1)需要 React 16.8 或以上,2)不支持 IE 11,3)map 和 set 不能直接用,需改用 valtio 提供的 proxyMap 和 proxySet。
import { proxy, proxyMap } from 'umi';
const state = proxy({
todos: proxyMap<number, Todo>([[1, {id:1,text:'Learn Umi'}]]),
filter: 'all',
});
可以直接测 store,也可以测基于 store 的 React 组件。正常写用例即可,后者推荐用 @testing-library/react。