StackBlitz 示例 - 打开新终端并
npm t
。
我阅读了act
所有渲染和触发的事件都包含在
中,所以你并不真正需要这个。act
所以如果我有一个简单的
useCounter
钩子:
function useCounter(args?: { init: number; by: number }) {
const init = args?.init || 0;
const by = args?.by || 1;
const [count, setCount] = useState(init);
const increment = () => setCount((p) => p + by);
const decrement = () => setCount((p) => p - by);
return { count, increment, decrement };
}
并隔离测试它:
test('state update in isolation', () => {
const { result } = renderHook((props) => useCounter(props), {
initialProps: { init: 5, by: 3 },
});
expect(result.current.count).toBe(5);
// act(() => result.current.increment()); // use this and test passes
result.current.decrement(); // use this and test fails: expected 8 and get 5
expect(result.current.count).toBe(8);
});
但是只有当我将 increment
包裹在
act
中时,我的测试才能通过。我以为它应该是自动包装的?所以我不确定应该如何使用
act
,什么时候暗示,什么时候不暗示?
我同时使用 act
和
renderHook
中的
@testing-library/react
,如果这有区别的话。
useCounter
这样的钩子时,如果您直接更改其状态(例如调用
result.current.decrement()
),则需要将该操作包装在
act()
中。尽管
renderHook()
已经处理了大部分事情,但钩子内的状态更新需要
act()
来确保您的测试行为一致。因此,在测试中直接修改状态时,请始终使用
act()
。您可以阅读这篇
中篇文章了解详细信息。