Реагировать useEffect hook, не вызывая ложную функцию - PullRequest
1 голос
/ 10 марта 2019

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

Итак, я новичок в React Hooks. Я использую хук useEffect () в компоненте, и этот хук вызывает функцию searchForVideos () из моего реквизита:

useEffect(() => {
  props.searchForVideos();
}, [currentPage]);

Эта функция проверяется в моих модульных тестах с использованием Jest:

const searchForVideos = jest.fn();

Итак, насколько я понимаю, useEffect () должен запускаться в первый раз сразу после рендеринга компонента. Я могу поместить оператор console.log () в обратный вызов useEffect (), и он будет печатать на консоль. Однако это ожидание () не выполняется:

const component = mountComponent();
setImmediate(() => {
    expect(searchForVideos).toHaveBeenCalled();
    done();
});

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

Есть ли что-то, что я должен знать о том, чтобы заставить смоделированные функции хорошо работать с перехватчиками React?

Редактировать: в ответ на комментарий я внес изменение, которое устранило проблему. Я не понимаю, почему это сработало.

const component = mountComponent();
requestAnimationFrame(() => {
    expect(searchForVideos).toHaveBeenCalled();
    done();
});

Так что я просто заменил setImmediate () на requestAnimationFrame (), и теперь все работает. Я никогда не трогал requestAnimationFrame () раньше. Насколько я понимаю, setImmediate () может заключаться в том, что он сразу же ставит в очередь обратный вызов в конце очереди событий, поэтому любые другие задачи JavaScript в очереди будут выполняться до него.

Так что я надеюсь, что кто-то мог бы лучше объяснить мне эти функции и почему это изменение сработало. Спасибо.

1 Ответ

0 голосов
/ 10 марта 2019

Что касается вашего второстепенного вопроса о том, почему requestAnimationFrame исправил это, см. Выдержки из документации ниже. Он просто попадает в конкретные сроки useEffect и useLayoutEffect - в частности, «useEffect откладывается до тех пор, пока браузер не выполнит рисование». requestAnimationFrame задерживает ваш тестовый код аналогичным образом. Я ожидаю, что если вы измените свой код на использование useLayoutEffect, оригинальная версия вашего теста будет работать (но useEffect - это подходящая ловушка для вашего случая).

С https://reactjs.org/docs/hooks-reference.html#timing-of-effects:

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

Однако не все эффекты могут быть отложены. Например, мутация DOM то, что видно пользователю, должно срабатывать синхронно до следующего рисовать так, чтобы пользователь не воспринимал визуальное несоответствие. (The Различие концептуально похоже на пассивное и активное событие. слушатели.) Для этих типов эффектов, React предоставляет один дополнительный Крюк называется useLayoutEffect. Он имеет ту же подпись, что и useEffect, и отличается только тогда, когда он уволен.

Хотя useEffect откладывается до тех пор, пока браузер не раскрасит, он гарантированно стреляет до любых новых рендеров. Всегда будет реагировать очистить эффекты предыдущего рендера перед началом нового обновления.

С https://reactjs.org/docs/hooks-reference.html#uselayouteffect:

Подпись идентична useEffect, но срабатывает синхронно после всех мутаций DOM. Используйте это, чтобы прочитать макет из DOM и синхронно перерисовать. Обновления, запланированные внутри useLayoutEffect, будут синхронно очищаться до того, как браузер получит возможность рисовать.

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

...