Javascript ES6 类 应该用作 React 状态吗?
Should Javascript ES6 Classes be Used as React State?
ES6 classes 是否应该直接用作 React 状态?
我想定义一个 ES6 class:
- 有成员变量显示在前端。 (对它们的更改触发 re-renders)
- 有方法可以在这些成员变量发生变化时定期将它们与我的后端同步。
然而,调用 setState
似乎不会区分 class 成员,至少据我所知。
使用以下 class:
class Document{
constructor(){
this.title = "";
this.body = "";
}
syncWithDatabase = async () => {
// do some logic to update the database
}
}
而这个组件:
// 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>
);
}
点击第一个按钮将在Document
保持反应状态的实例上设置标题和body,但它不会更新UI。
单击第二个按钮以我确信会起作用的方式强制执行 re-render 会使 document
的更新成员呈现出来,即使它们在 [=17= 时没有呈现] 叫做。
用 new Document()
创建一个新的 object 并传递它 setDocument
将 触发 re-render。所以我认为 React 没有进行深入比较,或者看到对 Document
object 的引用没有改变,因此 re-rending 没有改变。
那么,是否可以更改 object 的成员,将 object 传递给 setState 挂钩并让它更新 UI,而无需创建全新的 object?或者我应该避免做我想在这里做的事情吗?
您 可以 (但可能不应该,见下文)使用由构造函数创建的对象(这就是 document
在您的代码中的作用)作为状态。你不能做的是直接修改它(见the documentation):
document.title = 'Some Default Title'; // <=== INCORRECT
document.body = 'lorem text'; // <=== INCORRECT
document.syncWithDatabase();
setDocument(document); // <=== INCORRECT
相反,您需要创建一个新文档对象
const newDoc = new Document();
newDoc.title = 'Some Default Title';
newDoc.body = 'lorem text';
newDoc.syncWithDatabase();
setDocument(newDoc);
就是说,当使用 useState
钩子时,通常最好保持状态变量离散(一个用于 title
,一个用于 body
),这样改变一个并不需要同时改变另一个(当然,除非它们总是一起改变)。该文档讨论了here;这是一个引用:
...we recommend to split state into multiple state variables based on which values tend to change together.
(他们强调)
ES6 classes 是否应该直接用作 React 状态?
我想定义一个 ES6 class:
- 有成员变量显示在前端。 (对它们的更改触发 re-renders)
- 有方法可以在这些成员变量发生变化时定期将它们与我的后端同步。
然而,调用 setState
似乎不会区分 class 成员,至少据我所知。
使用以下 class:
class Document{
constructor(){
this.title = "";
this.body = "";
}
syncWithDatabase = async () => {
// do some logic to update the database
}
}
而这个组件:
// 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>
);
}
点击第一个按钮将在Document
保持反应状态的实例上设置标题和body,但它不会更新UI。
单击第二个按钮以我确信会起作用的方式强制执行 re-render 会使 document
的更新成员呈现出来,即使它们在 [=17= 时没有呈现] 叫做。
用 new Document()
创建一个新的 object 并传递它 setDocument
将 触发 re-render。所以我认为 React 没有进行深入比较,或者看到对 Document
object 的引用没有改变,因此 re-rending 没有改变。
那么,是否可以更改 object 的成员,将 object 传递给 setState 挂钩并让它更新 UI,而无需创建全新的 object?或者我应该避免做我想在这里做的事情吗?
您 可以 (但可能不应该,见下文)使用由构造函数创建的对象(这就是 document
在您的代码中的作用)作为状态。你不能做的是直接修改它(见the documentation):
document.title = 'Some Default Title'; // <=== INCORRECT
document.body = 'lorem text'; // <=== INCORRECT
document.syncWithDatabase();
setDocument(document); // <=== INCORRECT
相反,您需要创建一个新文档对象
const newDoc = new Document();
newDoc.title = 'Some Default Title';
newDoc.body = 'lorem text';
newDoc.syncWithDatabase();
setDocument(newDoc);
就是说,当使用 useState
钩子时,通常最好保持状态变量离散(一个用于 title
,一个用于 body
),这样改变一个并不需要同时改变另一个(当然,除非它们总是一起改变)。该文档讨论了here;这是一个引用:
...we recommend to split state into multiple state variables based on which values tend to change together.
(他们强调)