Почему useEffect не срабатывает при каждом рендере? - PullRequest
2 голосов
/ 01 апреля 2019

Мой компонент имеет два Rect.useEffect крючка

const Example = ({ user }) => {
  React.useEffect(() => {
    autorun(() => {
      console.log("inside autorun", user.count);
    });
  });

  // Only runs once
  React.useEffect(() => {
    console.log("Why not me?");
  });

  return <Observer>{() => <h1>{user.count}</h1>}</Observer>;
};

Я обновляю этот компонент, используя mobx. Это перерисовано правильно. Но "Why not me?" печатается только один раз.

Согласно официальным документам

По умолчанию эффекты запускаются после каждого завершенного рендеринга

Это означает, что console.log("Why not me?"); тоже должен запускаться каждый раз, когда проп user обновляется. Но это не так. Консольный вывод - это

В чем причина этого очевидного несоответствия?

Мой полный код можно посмотреть здесь

Edit mobx-useEffect query

Ответы [ 2 ]

3 голосов
/ 01 апреля 2019

В Mobx, так же как и компонент Observer, который обеспечивает обратный вызов функции рендеринга, функция autorun также выполняется независимо от жизненного цикла реакции.

Это происходит потому, что в качестве наблюдаемой переменной у вас есть число пользователей .

Согласно документам MOBX-реагирует

Observer - это компонент React, который применяет наблюдателя к анонимному регион в вашем компоненте. Для детей требуется один, без аргументов функция, которая должна возвращать ровно один компонент React. рендеринг в функции будет отслеживаться и автоматически перерисовывается при необходимости.

и документы MOBX

Когда используется autorun, предоставленная функция всегда будет срабатывать один раз сразу, а потом снова каждый раз одна из его зависимостей изменения.

Вы можете подтвердить это значение, войдя непосредственно в функциональный компонент, и вы заметите, что компонент отображается только один раз

РЕДАКТИРОВАТЬ:

Чтобы ответить на ваш вопрос

Если я изменю useEffect на

React.useEffect(autorun(() => {console.log("inside autorun", user.count)}));

в основном удаляет анонимную функцию из useEffect и просто передает автозапуск напрямую, тогда он запускается только один раз. Почему это так? Что такое разница?

Разница в том, что autorun возвращает disposer function, который при запуске избавится от autorun и больше не будет его выполнять.

Из документов:

Возвращаемое значение из автозапуска - это функция disposer, которая может быть используется для удаления автозапуска, когда он вам больше не нужен.

Теперь происходит следующее: поскольку useEffect выполняет обратный вызов, предоставленный ему при запуске, выполняемый обратный вызов - это функция disposer, возвращаемая функцией автозапуска, которая по существу отменяет ваш автозапуск.

1 голос
/ 01 апреля 2019

Похоже, ваш компонент не рендерится.autorun получает обратный вызов и может вызывать его независимо от рендера.

Example компонент перерисовывается только тогда, когда перерисовывается его родительский элемент или когда изменяется его реквизит.

Используйте этот код, чтобы наблюдать за тем, что происходит на самом деле:

const Example = ({ user }) => {
  console.log('render');
  React.useEffect(() => {
    console.log('useEffect autorun');
    autorun(() => {
      console.log("inside autorun", user.count);
    });
  });

  // Only runs once
  React.useEffect(() => {
    console.log("Why not me?");
  });

  return <Observer>{() => <h1>{user.count}</h1>}</Observer>;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...