admin管理员组文章数量:1435859
Should ES6 classes be used directly as React state?
I want to define an ES6 class that:
- Has member variables that will be displayed on the frontend. (changes to them trigger re-renders)
- Has methods that sync those member variables with my backend periodically as they change.
However, calling setState
does not appear to diff class members, at least as far as I can tell.
Using the following class:
class Document{
constructor(){
this.title = "";
this.body = "";
}
syncWithDatabase = async () => {
// do some logic to update the database
}
}
And this ponent:
// 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>
);
}
Clicking the first button will set the title and body on the instance of Document
held react state, but it will not update the UI.
Clicking the second button to force a re-render in a way that I am confident will work makes the updated members of document
render out, even though they didn't when setDocument
is called.
Creating a new object with new Document()
and passing it setDocument
WILL trigger a re-render. So I'm thinking that react isn't doing a deep pare or is seeing that the reference to the Document
object has not changed, and therefore not re-rending.
So, is it possible to change an object's members, pass that object to a setState hook and have it update the UI, without creating an entirely new object? Or should I avoid doing what I'm trying to do here?
Should ES6 classes be used directly as React state?
I want to define an ES6 class that:
- Has member variables that will be displayed on the frontend. (changes to them trigger re-renders)
- Has methods that sync those member variables with my backend periodically as they change.
However, calling setState
does not appear to diff class members, at least as far as I can tell.
Using the following class:
class Document{
constructor(){
this.title = "";
this.body = "";
}
syncWithDatabase = async () => {
// do some logic to update the database
}
}
And this ponent:
// 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>
);
}
Clicking the first button will set the title and body on the instance of Document
held react state, but it will not update the UI.
Clicking the second button to force a re-render in a way that I am confident will work makes the updated members of document
render out, even though they didn't when setDocument
is called.
Creating a new object with new Document()
and passing it setDocument
WILL trigger a re-render. So I'm thinking that react isn't doing a deep pare or is seeing that the reference to the Document
object has not changed, and therefore not re-rending.
So, is it possible to change an object's members, pass that object to a setState hook and have it update the UI, without creating an entirely new object? Or should I avoid doing what I'm trying to do here?
Share Improve this question asked Oct 27, 2019 at 17:44 Hunter HestonHunter Heston 231 silver badge3 bronze badges 3-
I'd avoid doing that. Modifying an instance's members doesn't modify the instance itself, so an equality check such as
===
is going to identify your instances as the same thing each time. – Jamie Dixon Commented Oct 27, 2019 at 17:46 - Actually your document should be a custom hook. The state should only contain data, and should not be mutated – Jonas Wilms Commented Oct 27, 2019 at 17:50
- You should not mutate state in React. – HMR Commented Oct 27, 2019 at 19:29
1 Answer
Reset to default 5You can (but probably shouldn't, see below) use an object created by a constructor function (which is what document
is in your code) as state. What you can't do is directly modify it as you are here (see the documentation):
document.title = 'Some Default Title'; // <=== INCORRECT
document.body = 'lorem text'; // <=== INCORRECT
document.syncWithDatabase();
setDocument(document); // <=== INCORRECT
Instead, you'd need to create a new document object
const newDoc = new Document();
newDoc.title = 'Some Default Title';
newDoc.body = 'lorem text';
newDoc.syncWithDatabase();
setDocument(newDoc);
That said, when using the useState
hook, you're usually better off keeping your state variables discrete (having one for title
and one for body
), so that changing one doesn't require also changing the other (unless, of course, they always change together). The documentation discusses that here; here's one quote:
...we remend to split state into multiple state variables based on which values tend to change together.
(their emphasis)
本文标签: reactjsShould Javascript ES6 Classes be Used as React StateStack Overflow
版权声明:本文标题:reactjs - Should Javascript ES6 Classes be Used as React State? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745653029a2668543.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论