Как проверить хуки с помощью двух операторов useEffect?
У меня есть следующий крючок:
const useBar = () => {
const [myFoo, setFoo] = useState(0);
const [myBar, setBar] = useState(0);
useEffect(() => {
setFoo(myFoo + 1);
console.log("setting foo (1)", myFoo, myBar);
}, [setFoo, myFoo, myBar]);
useEffect(() => {
setBar(myBar + 1);
console.log("setting bar (2)", myFoo, myBar);
}, [setBar, myBar, myFoo]);
};
При работе с компонентом у меня ожидаемое поведение бесконечного цикла:
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
const Bar = () => {
useBar();
return <div>Bar</div>;
};
function App() {
return (
<Bar />
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Из console.log:
setting foo (1) 1 1
setting bar (2) 1 1
setting foo (1) 2 2
setting bar (2) 2 2
setting foo (1) 3 3
setting bar (2) 3 3
...
Однако тестирование это с @testing-library/react-hooks
дает только первый вывод цикла:
describe("Tests", () => {
test("useBar", async () => {
const { rerender } = renderHook(() => {
return useBar();
});
// await waitForNextUpdate();
// tried the above doesn't work
// rerender();
// with rerender it loops through the next "cycle"
});
});
Было интересно, как правильно проверить хуки, не звоня rerender
и имитировать то же поведение, что и React - повторно визуализировать компонент при изменении состояния.
1 ответ
Я думаю, вы хотите проверить hook
который использует useEffect
и сообщить об ошибке, когда происходит бесконечный цикл. Но на самом деле мы не можем протестировать бесконечный цикл, мы можем установить ограничение только на количество раз. Когда цикл превышает этот предел, мы думаем, что он будет продолжать цикл бесконечно. Что касается того, является ли это на самом деле бесконечным циклом, это нелегко доказать.
Тем не менее, это не так просто проверить повторение useEffect
, Хотя с помощью waitForNextUpdate
может вызвать ошибку тайм-аута, эта ошибка также может быть вызвана длительной асинхронной операцией, и в качестве модульного теста вам понадобится быстрая обратная связь. Вы не можете ждать тайм-аут каждый раз. Это пустая трата времени.
Спасибо за эти проблемы, я нашел направление. Предоставить способ запуска useEffect из тестов
Когда я заменяю useEffect
с участием useLayoutEffect
Я могу получить Maximum update depth exceeded
ошибка быстро и точно. Это нужно только заменить useEffect
с участием useLayoutEffect
в обязательном тесте. Тест не пройден, когда цикл бесконечен.
import React from 'react'
import { renderHook } from '@testing-library/react-hooks'
import useBar from './useBar'
describe('Replace `useEffect` with `useLayoutEffect` to check for an infinite loop', () => {
let useEffect = React.useEffect
beforeAll(() => {
React.useEffect = React.useLayoutEffect
})
afterAll(() => {
React.useEffect = useEffect
})
it('useBar', async () => {
const { result } = renderHook(() => useBar())
})
})