
react数据监听
监听普通字段
js
import {useEffect, useState} from 'react';
function App() {
const [name, setName] = useState('Tom');
const [age, setAge] = useState(18);
const [summary, setSummary] = useState('');
useEffect(() => {
// 只要 name 或 age 任意一个变了,这里就会执行
// 并且这里的 name 和 age 都是最新的值
const newSummary = `姓名:${name},年龄:${age}`;
setSummary(newSummary);
}, [name, age]); // 👈 监听这两个字段
return (
<div>
<p>{summary}</p>
<button onClick={() => setAge(age + 1)}>年龄+1</button>
</div>
);
}
export default App;监听对象-方法1
重新赋值一个新对象
js
import {useEffect, useState} from 'react';
function App() {
const [config, setConfig] = useState({ mode: 'dark', version: 1 });
const [summary, setSummary] = useState({});
useEffect(() => {
console.log('⚠️ 监听到了 config 变化!');
// 注意:这里千万不要直接修改 config 对象,否则会导致死循环
setSummary(config);
}, [config]); // 👈 监听整个对象
const updateConfig = () => {
// ✅ 正确做法:创建一个新的对象(新内存地址)
setConfig({ ...config, version: config.version + 1 });
};
return (
<div>
<p>{JSON.stringify(summary)}</p>
<button onClick={updateConfig}>年龄+1</button>
</div>
);
}
export default App;监听对象-方法2
简单粗暴,适合对象属性很多且都需要监听的情况
js
import { useEffect, useRef, useState } from 'react';
function App() {
const [form, setForm] = useState({ a: 1, b: 2 });
const [lastChangedField, setLastChangedField] = useState(null);
// 记住上一次的值,必须用useRef
const prevFormRef = useRef(form);
useEffect(() => {
// 找出哪个字段发生了变化
const prevForm = prevFormRef.current;
const changedFields = [];
if (prevForm.a !== form.a) {
changedFields.push(`a: ${prevForm.a} → ${form.a}`);
}
if (prevForm.b !== form.b) {
changedFields.push(`b: ${prevForm.b} → ${form.b}`);
}
if (changedFields.length > 0) {
setLastChangedField(changedFields.join(', '));
console.log('表单的任意字段变了!', changedFields);
}
// 更新 ref
prevFormRef.current = form;
}, [JSON.stringify(form)]);
const updateA = () => {
setForm(prev => ({ ...prev, a: prev.a + 1 }));
};
const updateB = () => {
setForm(prev => ({ ...prev, b: prev.b + 1 }));
};
const resetForm = () => {
setForm({ a: 1, b: 2 });
setLastChangedField(null);
};
return (
<div style={{ padding: '20px', fontFamily: 'Arial' }}>
<h2>表单监控</h2>
<div style={{ marginBottom: '20px' }}>
<p>当前表单值:</p>
<p>a = <strong>{form.a}</strong></p>
<p>b = <strong>{form.b}</strong></p>
</div>
<div style={{ marginBottom: '20px' }}>
<button onClick={updateA} style={{ marginRight: '10px' }}>
增加 a
</button>
<button onClick={updateB} style={{ marginRight: '10px' }}>
增加 b
</button>
<button onClick={resetForm}>
重置
</button>
</div>
{lastChangedField && (
<div style={{
padding: '10px',
backgroundColor: '#e3f2fd',
borderRadius: '5px',
borderLeft: '4px solid #2196f3'
}}>
🔔 发生变化:{lastChangedField}
</div>
)}
<div style={{
marginTop: '20px',
padding: '10px',
backgroundColor: '#f5f5f5',
borderRadius: '5px',
fontSize: '12px',
color: '#666'
}}>
💡 提示:使用 JSON.stringify 监听整个对象的变化
</div>
</div>
);
}
export default App;监听对象字段
js
import {useEffect, useRef, useState} from 'react';
function App() {
const [userInfo, setUserInfo] = useState({ name: 'Jack', age: 20, token: 'abc' });
const isFirstRender = useRef(true);
// ✅ 场景:我只关心 age 变了没,name 变了我不 care
useEffect(() => {
// 如果你希望只在 age 真正变化时执行(而排除初始挂载),可以加一个 useRef 跳过第一次:
if (isFirstRender.current) {
isFirstRender.current = false;
return;
}
console.log('👴 用户年龄变了,请求老年版接口...');
}, [userInfo.age]); // 👈 只监听 age 字段
return <div>当前用户:{userInfo.name}</div>;
}
export default App;监听数组
js
import {useEffect, useRef, useState} from 'react';
function App() {
const [list, setList] = useState([1, 2, 3]);
// ✅ 监听数组长度:只要增加或删除元素,就会触发
useEffect(() => {
console.log('列表长度变了,当前长度:', list.length);
}, [list.length]);
// ✅ 监听特定项:比如只监听第 0 个元素
// 注意:如果数组可能为空,需要加可选链 ?.
useEffect(() => {
console.log('列表的第一项变了:', list[0]);
}, [list[0]]);
return <button onClick={() => setList([...list, list.length + 1])}>添加</button>;
}
export default App;
