useWatch / useWatchEffect

订阅 store 状态变化和执行副作用,不会触发组件重新渲染

useWatch

useWatch 是一个 React Hook,允许你订阅 store 的状态变化,并执行副作用。

它类似于 useStoreValue,但不会在状态变化时触发组件重新渲染,非常适合执行副作用。

例如,你可以用它来记录状态变化:

useWatch(
  () => counterStore.value.count,
  (current, prev) => {
    console.log("count 变化了", current, prev);
  }
);

默认情况下,它会在状态变化时触发副作用,而非立即执行。

立即执行

如果你想立即触发副作用,可以使用 immediate: true 选项。

useWatch(
  () => counterStore.value.count,
  (current, prev) => {
    console.log("立即执行副作用", current, prev);
  },
  { immediate: true }
);

只运行一次

如果你只想触发一次副作用,可以使用 once: true 选项。

useWatch(
  () => counterStore.value.count,
  (current, prev) => {
    console.log("只运行一次", current, prev);
  },
  { once: true }
);

清理函数

你也可以返回一个函数来清理副作用。清理函数会在组件卸载或下一个副作用运行前执行。

useWatch(
  () => counterStore.value.count,
  (current, prev) => {
    if (current > 10) {
      const handleClick = () => {
        console.log("当前计数", counterStore.value.count);
      };
      window.addEventListener("click", handleClick);
      return () => {
        window.removeEventListener("click", handleClick);
      };
    }
  }
);

监听多个 store

你也可以同时监听多个 store。

useWatch(
  () => [counterStore.value, userStore.value] as const, // ✅ 使用 `as const` 推断类型
  ([counter, user]) => {
    console.log("counter 和 user 变化了", counter.count, user.name);
  }
);

注意:

  • 如果你想监听 store 数组,可以使用 [x, y, z] as const 来自动推断 TypeScript 类型。

useWatchEffect

useWatchEffect 类似于 useWatch,但副作用会在构建组件时立即运行。

它会自动收集依赖并在依赖变化时触发副作用。

useWatchEffect(() => {
  if (counterStore.value.count > 10) {
    console.log("count 大于 10");
  }
});

同时支持清理函数。

useWatchEffect(() => {
  if (counterStore.value.count > 10) {
    const handleClick = () => {
      console.log("当前计数", counterStore.value.count);
    };
    window.addEventListener("click", handleClick);
    return () => {
      window.removeEventListener("click", handleClick);
    };
  }
});