useWatch
在响应式数据变化时执行副作用,不会触发组件重新渲染
API 参考
语法
const currentValue = useWatch(watchSource, callback, options?)
参数
watchSource
: 要监听的 store 实例、计算函数或源数组callback
: 监听数据变化时执行的函数(可返回清理函数)options
(可选):immediate
: 立即使用当前值执行回调(默认:false)once
: 仅执行一次回调,然后停止监听(默认:false)deep
: 启用深度比较以处理嵌套对象(默认:false)
返回值
currentValue
: 监听源的最新状态值
配置选项
立即执行
useWatch(
() => userStore.value.preferences,
(preferences) => {
applyUserPreferences(preferences);
},
{ immediate: true } // 构建组件时立即执行回调
);
只执行一次
useWatch(
() => userStore.value.isLoggedIn,
(isLoggedIn) => {
if (isLoggedIn) {
console.log("检测到首次登录!");
showWelcomeMessage();
}
},
{ once: true } // 仅触发一次
);
深度比较
const configStore = createStore({
api: {
endpoints: { users: "/api/users", orders: "/api/orders" },
timeout: 5000,
},
});
useWatch(
() => configStore.value.api,
(apiConfig, prevApiConfig) => {
console.log("API 配置已更改");
reinitializeApiClient(apiConfig);
},
{ deep: true } // 深度比较,以避免不必要的副作用执行
);
示例
监听 Store 变化
跟踪 store 变化用于日志、分析或外部 API 调用:
const counterStore = createStore({ count: 0 });
function Counter() {
// 仅监听变化,不触发重新渲染
useWatch(counterStore, (current, prev) => {
console.log(`计数: ${prev.count} → ${current.count}`);
// 跟踪分析,比如埋点
analytics.track("counter_changed", {
from: prev.count,
to: current.count,
});
});
return (
<button onClick={() => counterStore.setState((s) => s.count++)}>
增加
</button>
);
}
监听计算值
监控计算值的业务逻辑:
const userStore = createStore({
firstName: "张",
lastName: "三",
age: 30,
});
function UserTracker() {
// 监听全名变化
useWatch(
() => `${userStore.value.firstName}${userStore.value.lastName}`,
(fullName, prevFullName) => {
if (prevFullName) {
console.log(`姓名更新: "${prevFullName}" → "${fullName}"`);
api.updateUserProfile({ fullName });
}
}
);
// 监听年龄里程碑
useWatch(
() => userStore.value.age,
(age, prevAge) => {
if (age >= 18 && prevAge < 18) {
console.log("用户已成年!");
unlockAdultFeatures();
}
}
);
return <div>正在跟踪用户变化...</div>;
}
监听多个源
同时监听多个 store 的变化:
const userStore = createStore({ name: "张三", role: "user" });
const settingsStore = createStore({ theme: "light", language: "zh" });
function AppWatcher() {
useWatch(
() => [userStore.value, settingsStore.value] as const,
([user, settings], [prevUser, prevSettings]) => {
// 基于角色的逻辑
if (user.role !== prevUser?.role) {
console.log(`角色变化: ${prevUser?.role} → ${user.role}`);
redirectBasedOnRole(user.role);
}
// 主题持久化
if (settings.theme !== prevSettings?.theme) {
console.log(`主题: ${prevSettings?.theme} → ${settings.theme}`);
document.body.className = settings.theme;
localStorage.setItem("theme", settings.theme);
}
}
);
return <div>监控应用状态...</div>;
}
清理函数
常用于管理订阅、定时器和外部资源等场景:
function WebSocketManager() {
useWatch(
() => userStore.value.connectionId,
(connectionId, prevConnectionId) => {
if (!connectionId) return;
console.log(`连接到: ${connectionId}`);
const ws = new WebSocket(`ws://api.com/${connectionId}`);
ws.onopen = () => console.log("已连接");
ws.onmessage = (event) => handleMessage(event.data);
ws.onerror = (error) => console.error("WebSocket 错误:", error);
// 清理函数 - 在下次变化或卸载时自动调用
return () => {
console.log(`断开连接: ${connectionId}`);
ws.close();
};
}
);
return <div>WebSocket 管理器已激活</div>;
}
最佳实践
✅ 仅用于副作用
// Good:外部副作用
useWatch(
() => store.value.theme,
(theme) => {
document.body.className = theme;
localStorage.setItem("theme", theme);
}
);
❌ 不要用于组件状态
// Bad:不必要的间接状态
const [displayValue, setDisplayValue] = useState("");
useWatch(
() => store.value.data,
(data) => {
setDisplayValue(data); // 应该使用 useStoreValue 替代
}
);
✅ 明确监听指定属性变化
// Good:监听特定属性
useWatch(
() => userStore.value.email,
(email) => {
validateEmail(email);
}
);
❌ 避免监听所有状态
// Bad:任何 store 变化都会触发
useWatch(
() => largeStore.value,
(store) => {
console.log("某些内容变化了"); // 太宽泛了
}
);
✅ 始终清理资源
// Good:正确清理
useWatch(
() => store.value.intervalMs,
(ms) => {
const interval = setInterval(doSomething, ms);
return () => clearInterval(interval);
}
);
Hook 比较
Hook | 用途 | 重新渲染 | 自动跟踪 | 最适用于 |
---|---|---|---|---|
useWatch | 监听状态变化并执行副作用 | ❌ 否 | ❌ 否 | 特定副作用 |
useWatchEffect | 自动追踪依赖的响应式副作用 | ❌ 否 | ✅ 是 | 一般副作用 |
useStoreValue | 同步 store 最新状态 | ✅ 是 | ❌ 否 | UI 状态 |
useComputed | 响应式更新的计算值 | ✅ 是 | ✅ 是 | 计算数据 |
相关 Hook
useWatchEffect
- 自动跟踪响应式副作用useStoreValue
- 同步 store 最新状态useComputed
- 响应式更新的计算值