React中如何监听Class类实例对象的变化?
问题
我在React应用中尝试监听Class类实例对象的变化,能看到类实例的hunger值已改变,但useEffect无法监听到该变化!
Person类定义:
class Person { constructor(name) { this.name = name; this.hunger = 0; } increaseHunger() { this.hunger += 10; } } export default Person;
React组件代码:
import React from "react"; import Person from "./classes/Person"; export default function App() { const [person, setPerson] = React.useState(new Person("John")); React.useEffect(() => { console.log("Effect"); }, [person.hunger]); return ( <div> <div>{person.name}</div> <div>{person.hunger}</div> <button onClick={() => person.increaseHunger()}>Click</button> </div> ); }
点击按钮后hunger值确实变化,但useEffect日志从未触发,我猜测是person对象引用未改变,却不知具体原因,请问我哪里出错了?
原因
- React状态更新逻辑限制:useState存储的
person是对象引用,直接调用person.increaseHunger()修改实例的hunger属性,并没有改变person对象本身的引用地址。React通过对比状态的引用变化判断是否重渲染,引用不变则组件不会更新,useEffect的依赖检查也不会触发。 - useEffect依赖项的执行前提:即使把
person.hunger作为依赖项,组件不重渲染的话,useEffect根本不会进入依赖对比流程,自然不会执行回调。
解决方法
方法一:创建新实例更新状态
每次修改属性时,通过setPerson传入新的Person实例,让React检测到引用变化,触发重渲染和useEffect:
<button onClick={() => { const newPerson = new Person(person.name); newPerson.hunger = person.hunger + 10; setPerson(newPerson); }}>Click</button>
或者复用类方法并保留原型链:
<button onClick={() => { const newPerson = Object.assign(Object.create(Object.getPrototypeOf(person)), person); newPerson.increaseHunger(); setPerson(newPerson); }}>Click</button>
方法二:拆分独立状态(更推荐)
将hunger拆成单独的useState状态,符合React状态管理的常规思路,也避免了类实例的引用问题:
import React from "react"; export default function App() { const [name] = React.useState("John"); const [hunger, setHunger] = React.useState(0); React.useEffect(() => { console.log("Effect"); }, [hunger]); return ( <div> <div>{name}</div> <div>{hunger}</div> <button onClick={() => setHunger(prev => prev + 10)}>Click</button> </div> ); }
内容的提问来源于stack exchange,提问作者Rohr Facu
相关产品推荐
相关产品推荐

