React状态对象的Fast Refresh + Update函数实现

Fast Refresh + Update function implementation of object that is in React state

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

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

假设我的 class 汽车如下所示:

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 状态的对象更新?

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

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

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

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

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

这实际上有点棘手,因为您要实现的目标在某种程度上违背了 React 围绕不可变的设计。使用 Object.setPrototypeOf(car, Car.prototype).

可以轻松地直接更改 classes 方法并将其分配给现有实例

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

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

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

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

这可以放在 useEffect 中,它会 运行 每次原始 Car class 改变时

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

 useEffect(() => {
    setCar(Object.assign(Object.create(Car.prototype), car))
  }, [])