直接上代码
import create from 'zustand';
import { immer } from 'zustand/middleware';
const useStore = create(
immer((set, get) => ({
// 初始状态
nestedObject: {
aaa: {
bb: {
cc: 0,
},
dd: 1,
},
eee: 2,
},
// 封装 set 方法以便能够深度设置状态
setNestedValue: (fullPath, value) => {
// 分割路径
const [rootKey, ...subPath] = fullPath.split('.');
const subKeyPath = subPath.join('.');
// 检查根键是否存在
if (!(rootKey in get())) {
throw new Error(`Root key "${rootKey}" does not exist in the state.`);
}
// 获取根对象
const rootObject = get()[rootKey];
// 验证子路径是否存在(这里只是检查,不创建)
let current = rootObject;
const keys = subKeyPath.split('.');
for (let i = 0; i < keys.length - 1; i++) {
const key = keys[i];
if (!(key in current)) {
throw new Error(`Subpath "${subKeyPath.slice(0, i + 1)}" does not exist in the state.`);
}
current = current[key];
}
// 设置最后一个键的值
const lastKey = keys[keys.length - 1];
set((state) => {
// 使用 immer 的 set 功能来安全地更新值
state[rootKey][lastKey] = value;
});
},
}))
);
// 使用 store(这通常在 React 组件内部进行)
function MyComponent() {
const { nestedObject, setNestedValue } = useStore();
// 使用 setNestedValue 来设置任何深度的值(确保路径存在)
setNestedValue('nestedObject.aaa.bb.cc', 100); // 更新现有的值
// 注意:如果尝试设置不存在的路径,将会抛出错误
// setNestedValue('nestedObject.aaa.ff.gg', 'new value'); // 这会抛出错误,因为 'ff' 不存在
// 渲染一些状态以验证更改
return (
<div>
<pre>{JSON.stringify(nestedObject, null, 2)}</pre>
</div>
);
}
// 确保在 React 应用中使用 MyComponent