react怎么实现watch
监听状态变化
在React中,可以通过useEffect钩子来监听状态的变化,类似于Vue中的watch功能。useEffect会在依赖项发生变化时执行回调函数。
import { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log('count changed:', count);
}, [count]);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
监听多个状态
如果需要监听多个状态变量,可以将它们都添加到useEffect的依赖数组中。当其中任何一个状态发生变化时,回调函数都会执行。
const [name, setName] = useState('');
const [age, setAge] = useState(0);
useEffect(() => {
console.log('name or age changed:', name, age);
}, [name, age]);
监听对象属性
如果需要监听对象的某个属性变化,可以使用useMemo来记忆该属性,然后在useEffect中监听这个记忆值。

const [user, setUser] = useState({ name: '', age: 0 });
const userName = useMemo(() => user.name, [user]);
useEffect(() => {
console.log('user name changed:', userName);
}, [userName]);
监听初次渲染
如果只想在组件初次渲染时执行某些逻辑,可以传递一个空数组作为useEffect的依赖项。
useEffect(() => {
console.log('Component mounted');
}, []);
清理副作用
useEffect可以返回一个清理函数,用于在组件卸载或依赖项变化时执行清理操作。

useEffect(() => {
const timer = setInterval(() => {
console.log('Timer tick');
}, 1000);
return () => {
clearInterval(timer);
};
}, []);
自定义Hook封装
可以将监听逻辑封装成自定义Hook,方便复用。
function useWatch(value, callback) {
useEffect(() => {
callback(value);
}, [value]);
}
function Example() {
const [count, setCount] = useState(0);
useWatch(count, (newValue) => {
console.log('count changed:', newValue);
});
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
性能优化
对于复杂的监听逻辑,可以使用useMemo和useCallback来优化性能,避免不必要的计算和渲染。
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
const memoizedCallback = useCallback(() => {
doSomething(a, b);
}, [a, b]);
第三方库
如果需要更强大的监听功能,可以考虑使用第三方库如react-use中的usePrevious或useObservable等Hook。
import { usePrevious } from 'react-use';
function Example() {
const [count, setCount] = useState(0);
const prevCount = usePrevious(count);
useEffect(() => {
if (prevCount !== count) {
console.log('count changed from', prevCount, 'to', count);
}
}, [count, prevCount]);
}






