0

假设我有一个 React 应用程序,它有一个内部状态,我在其中存储一个对象,比如

  const [car, setCar] = useState(new Car());

假设我的班级 Car 如下所示:

class Car {
  constructor(brand) {
    this.carname = brand;
  }

  present() {
    return "I have a " + this.carname;
  }
}

当我运行和调试应用程序时,我可以将 Car 对象保存到状态中并检索它并调用 present()。

现在,当我对 present() 函数进行更改时,例如

  present() {
    return "I have a " + this.carname + " and it is shiny";
  }

然后由于快速刷新,我的应用程序被刷新了。但不幸的是,因为对象已经存储了状态,所以它不会收到函数实现的更新。

有没有一种方法可以更改代码,以便通过快速刷新功能实现也将针对处于 React 状态的对象进行更新?

我尝试通过原型更新该方法,但它也不起作用。

4

2 回答 2

0

按照设计,快速刷新将尽可能保留状态。然而,无论依赖数组中有什么,useEffect 都会在快速刷新期间更新。只要你提供一个空的依赖数组,你就可以在 useEffect 中使用 setState 来改变快速刷新之间的状态。

 const [car, setCar] = useState(new Car());

 useEffect(() => {
    setCar(new Car());
  },[])

但请记住,useEffect 只会在第一次渲染后运行,因此您需要new Car()在 useState 挂钩参数中保留默认状态,以防止任何未定义的错误。

于 2020-10-01T18:04:39.193 回答
0

这实际上有点棘手,因为您试图实现的目标与 react 围绕不可变的设计有些背道而驰。直接更改类方法并将其分配给现有实例可以使用Object.setPrototypeOf(car, Car.prototype).

这替换了原始汽车实例的原型并更改了方法实现。正如您所说,这不起作用,因为改变对象不会触发重新渲染。

useState 比较Object.is()在这种情况下不会触发重新渲染的对象,因为两个对象具有相同的引用。

为了方便起见Object.is(),您需要将具有新原型和现有实例的确切属性的新对象传递给setCar(). 这不能使用基本的扩展运算符来完成,{..car}或者Object.assign({}, car)因为这些方法只复制对象自己的可枚举属性。

您可以改为使用以下内容创建一个具有与新原型完全相同的属性的新对象setCar(Object.assign(Object.create(Car.prototype), car))

这可以放在 useEffect 中,它将在每次更改原始 Car 类时运行

 const [car, setCar] = useState(new Car());

 useEffect(() => {
    setCar(Object.assign(Object.create(Car.prototype), car))
  }, [])
于 2020-10-02T04:12:29.113 回答