Javascript ES6 类应该用作 React State 吗?

Hun*_*ton 2 javascript reactjs es6-class react-hooks

ES6 类应该直接用作 React 状态吗?

我想定义一个 ES6 类:

  1. 具有将显示在前端的成员变量。(对它们的更改会触发重新渲染)
  2. 有方法在这些成员变量发生变化时定期将其与我的后端同步。

然而,setState至少据我所知,调用似乎并不区分类成员。

使用以下类:

class Document{
  constructor(){
    this.title = "";
    this.body = "";
  }


  syncWithDatabase = async () => {
    // do some logic to update the database 
  }

}
Run Code Online (Sandbox Code Playgroud)

这个组件:


// import Document from "...";

export default function Sandbox() {
  const [document, setDocument] = useState(new Document());
  const [renderTrigger, setRenderTrigger] = useState(false);

  return (
    <div>
      <div>{document.title}</div>
      <div>{document.body}</div>
      <button
        onClick={() => {
          document.title = 'Some Default Title';
          document.body = 'lorem text';
          document.syncWithDatabase(); // being able to take this type of action in this way is why I'm trying to use classes. 
          setDocument(document);
        }}
      >
        Set Canned Data
      </button>

      <div>Render trigger is: {renderTrigger ? 'true' : 'false'}</div>
      <button onClick={() => setRenderTrigger(true)}>Force Render</button>

   </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

单击第一个按钮将在保持反应状态的实例上设置标题和正文Document,但不会更新 UI。

单击第二个按钮以我确信会起作用的方式强制重新渲染,会使更新的渲染成员document输出,即使它们在setDocument调用时没有这样做。

使用它创建一个新对象new Document()并传递它setDocument 将会触发重新渲染。所以我认为反应没有进行深度比较,或者看到对对象的引用Document没有改变,因此没有重新渲染。

那么,是否可以更改对象的成员、将该对象传递给 setState 挂钩并让它更新 UI,而无需创建全新的对象?或者我应该避免做我在这里想做的事情吗?

T.J*_*der 5

可以document(但可能不应该,请参见下文)使用由构造函数(即代码中的内容)创建的对象作为状态。你不能做的是直接修改它,因为你在这里(请参阅文档):

document.title = 'Some Default Title'; // <=== INCORRECT
document.body = 'lorem text';          // <=== INCORRECT
document.syncWithDatabase();
setDocument(document);                 // <=== INCORRECT
Run Code Online (Sandbox Code Playgroud)

相反,您需要创建一个新的文档对象

const newDoc = new Document();
newDoc.title = 'Some Default Title';
newDoc.body = 'lorem text';
newDoc.syncWithDatabase();
setDocument(newDoc);
Run Code Online (Sandbox Code Playgroud)

也就是说,在使用useState钩子时,通常最好保持状态变量离散(一个 for title,一个 for body),这样改变一个就不需要同时改变另一个(当然,除非它们总是一起改变) )。该文档在这里讨论了这一点;这是引用的一句话:

...我们建议根据值倾向于一起变化的情况将状态拆分为多个状态变量。

(他们的强调)

  • @HunterHeston - JavaScript 引擎在创建对象方面***非常***快,并且在回收内存方面非常聪明,但总有*机会*它可能成为一个问题。但是,如果您希望将状态组合在一个对象中,那么这几乎是您唯一的选择,因为如果您再次提供相同的对象,“useState”提供的设置器将忽略您。(我可以想到一些奇怪的方法来强制重新渲染,同时避免创建新对象,但如果没有大量的测试[每次React发布点时都重复该测试],我会对这样做持谨慎态度。 ) (2认同)