gpt4 book ai didi

reactjs - 测试自定义 Hook 并收到“警告 : An update to TestHook inside a test was not wrapped in act

转载 作者:行者123 更新时间:2023-12-05 06:25:54 25 4
gpt4 key购买 nike

编辑: 我找到了一个解决方案,来自 this video来自 Kent C. Dodds。

只需将 jest.advanceTimersByTime 调用包装在一个 act 函数中。

所以这样:

jest.advanceTimersByTime(510);

变成:

act(()=>jest.advanceTimersByTime(510));

我已经实现了一个简单的自定义 Hook ,以消除值更新的抖动。

代码如下:

function useDebounce(value, delay) {
const [debouncedValue, setDebouncedValue] = useState(value);

useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);

return () => {
clearTimeout(handler);
};
}, [value, delay]);

return debouncedValue;
}

这个钩子(Hook)的客户端是这样的(非常简单):

function Search(props) {
const [searchTerm, setSearchTerm] = useState('');
const debouncedSearchTerm = useDebounce(searchTerm, 500);

// doing something useful with debouncedSearchTerm....
// ...
// ...
}

因此,我正在尝试使用以下代码测试 Hook :

import { renderHook, act } from 'react-hooks-testing-library';
import useDebounce from '../useDebounce';

jest.useFakeTimers();

it.only('should update value after specified delay', () => {
const { result, rerender } = renderHook(
({ value, delay }) => useDebounce(value, delay),
{ initialProps: { value: '', delay: 500 } }
);

expect(result.current).toBe('');
jest.advanceTimersByTime(510);
expect(result.current).toBe('');

rerender({ value: 'Hello World', delay: 500 });

expect(result.current).toBe('');
jest.advanceTimersByTime(498);
expect(result.current).toBe('');
jest.advanceTimersByTime(3);
expect(result.current).toBe('Hello World');
});

虽然测试通过了,但我收到以下警告:

console.error node_modules/react-test-renderer/cjs/react-test-renderer.development.js:102

Warning: An update to TestHook inside a test was not wrapped in act(...). When testing, code that causes React state updates should be wrapped into act(...): act(() => { /* fire events that update state */ }); /* assert on the output */ This ensures that you're testing the behavior the user would see in the browser. Learn more at..... in TestHook in Suspense

我知道如果我要调用一个函数来更新钩子(Hook)的内部状态(例如 useCounter 钩子(Hook)的 increment()),我必须在 act 功能,如文档所述。

但是,我已经实现的 useDebounce Hook 通过内部 useEffect 改变状态,只要值或延迟发生变化,它就会运行。

我怎样才能摆脱这个警告?我的代码有问题吗?我是不是忘记在测试代码中添加一些东西了?

请帮忙!

最佳答案

将这一行包装到 act 中:

it.only('should update value after specified delay', () => {
const { result, rerender } = renderHook(
({ value, delay }) => useDebounce(value, delay),
{ initialProps: { value: '', delay: 500 } }
);

expect(result.current).toBe('');
jest.advanceTimersByTime(510);
expect(result.current).toBe('');

rerender({ value: 'Hello World', delay: 500 });

expect(result.current).toBe('');
jest.advanceTimersByTime(498);
expect(result.current).toBe('');
// once delay time is passed, component is rerendered, so to capture that
// in unit test, this line should be wrapped in act
act(() => jest.advanceTimersByTime(3));
expect(result.current).toBe('Hello World');
});```

关于reactjs - 测试自定义 Hook 并收到“警告 : An update to TestHook inside a test was not wrapped in act,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56611970/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com