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 component:
// 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 compare 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?