usePick

按需订阅 store 指定状态变化

为什么使用 usePick?

专为性能优化而设计 - 仅在实际使用的特定属性发生变化时才重新渲染。

性能比较

const userStore = createStore({
  name: "张三",
  age: 30,
  email: "zhangsan@example.com",
  avatar: "avatar.jpg",
  preferences: { theme: "dark", language: "zh" },
  lastLogin: new Date(),
});

// ❌ Bad:任何 store 状态变化都会触发重新渲染
function UserName() {
  const user = useStoreValue(userStore);
  return <h1>{user.name}</h1>; // 仅使用 name,但订阅了所有状态
}

// ✅ Good:仅在 name 变化时重新渲染
function OptimizedUserName() {
  const { name } = usePick(userStore, "name");
  return <h1>{name}</h1>; // 只订阅需要的属性
}

API 参考

语法

const selectedFields = usePick(store, ...keys);
const selectedFields = usePickDeeply(store, ...keys); // 深度相等检查

参数

  • store: ZenBox store 实例
  • ...keys: 要从 store 中选择的属性名称

返回值

仅包含从 store 中选择的属性的对象。

示例

单个属性

function UserName() {
  // 仅在 name 变化时重新渲染
  const { name } = usePick(userStore, "name");
  return <h1>{name}</h1>;
}

多个属性

function UserContact() {
  // 仅在 name 或 email 变化时重新渲染
  const { name, email } = usePick(userStore, "name", "email");

  return (
    <div>
      <h2>{name}</h2>
      <p>邮箱: {email}</p>
    </div>
  );
}

深度比较

对于需要深度比较的嵌套对象:

const settingsStore = createStore({
  theme: {
    colors: { primary: "#blue", secondary: "#gray" },
    fonts: { heading: "Arial", body: "Helvetica" },
  },
  notifications: {
    email: true,
    push: false,
  },
});

function ThemeSettings() {
  // 启用深度比较,避免不必要的重新渲染
  const { theme } = usePickDeeply(settingsStore, "theme");

  return (
    <div
      style={{
        color: theme.colors.primary,
        fontFamily: theme.fonts.heading,
      }}
    >
      当前主题配置
    </div>
  );
}

usePick vs useStoreValue

方法代码性能
usePickusePick(store, "name", "email")✅ 最佳 - 仅特定属性
useStoreValue + pickuseStoreValue(store, { pick: ["name", "email"] })✅ 相同性能,更冗长
useStoreValueuseStoreValue(store)❌ 任何变化都会重新渲染

最佳实践

明确属性选择

// ❌ Bad:不选择任何属性(等同于 useStoreValue)
const { name } = usePick(userStore);

// ❌ Bad:选择太多属性
const { name } = usePick(userStore, "name", "age", "email", "avatar");

// ✅ Good:仅选择所需属性
const { name, status } = usePick(userStore, "name", "status");

将相关属性分组

// ❌ Bad:过于细粒度
const { name } = usePick(userStore, "name");
const { email } = usePick(userStore, "email");
const { age } = usePick(userStore, "age");

// ✅ Good:分组相关属性
const { name, email, age } = usePick(userStore, "name", "email", "age");

相关 Hook