Должны ли классы Javascript ES6 использоваться в качестве React State? - PullRequest
1 голос
/ 27 октября 2019

Должны ли классы ES6 использоваться непосредственно как состояние React?

Я хочу определить класс ES6, который:

  1. Имеет переменные-члены, которые будут отображаться во внешнем интерфейсе. (изменения в них вызывают повторное рендеринг)
  2. Имеет методы, которые периодически синхронизируют эти переменные-члены с моим бэкэндом при их изменении.

Тем не менее, вызов setState не выглядит для членов класса diff, по крайней мере, насколько я могу судить.

Используя следующий класс:

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удерживается реагирующее состояние, но не будет обновлять пользовательский интерфейс.

Нажатие второй кнопки для принудительного повторного рендеринга, которое, я уверен, сработает, приводит к обновлению членов document, даже если они не вызывались при вызове setDocument.

Создание нового объекта с new Document() и передача его setDocument WILL вызывает повторную визуализацию. Так что я думаю, что реакция не делает глубокого сравнения или видит, что ссылка на объект Document не изменилась, и, следовательно, не повторно отображает.

Итак, возможно ли изменить члены объекта, передать этот объект в хук setState и обновить его пользовательский интерфейс, не создавая совершенно новый объект? Или я должен избегать делать то, что я пытаюсь сделать здесь?

1 Ответ

1 голос
/ 27 октября 2019

Вы можете (но, вероятно, не должны, см. Ниже) использовать объект, созданный функцией конструктора (что и есть document в вашем коде) в качестве состояния. То, что вы не можете сделать - это напрямую изменить его, как вы здесь (см. документацию ):

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), так что для изменения одного не нужно также менять другого (если, конечно, они всегда не изменяются вместе). В документации обсуждается, что здесь ;вот одна цитата:

... мы рекомендуем разделить состояние на несколько переменных состояния, в зависимости от того, какие значения имеют тенденцию изменяться вместе.

(их акцент)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...