React Hook
React Hooks 是 React 16.8 版本引入的新特性,它允许在不编写 class 组件的情况下使用 state 和其他 React 特性。Hooks 提供了一种更简洁直观的方式来编写函数组件并复用状态逻辑。

如何在 Jest 中测试 React Hooks?如何使用 renderHook 和 act?Jest 提供了多种测试 React Hooks 的方法,主要使用 `@testing-library/react-hooks`:
**1. 测试 useState:**
```javascript
import { renderHook, act } from '@testing-library/react-hooks';
test('useState hook', () => {
const { result } = renderHook(() => useCounter(0));
expect(result.current.count).toBe(0);
act(() => {
result.current.increment();
});
expect(result.current.count).toBe(1);
});
```
**2. 测试 useEffect:**
```javascript
test('useEffect hook', () => {
const { result } = renderHook(() => useFetch('/api/data'));
expect(result.current.loading).toBe(true);
await act(async () => {
await waitFor(() => !result.current.loading);
});
expect(result.current.data).toBeDefined();
});
```
**3. 测试 useContext:**
```javascript
test('useContext hook', () => {
const wrapper = ({ children }) => (
<ThemeContext.Provider value="dark">
{children}
</ThemeContext.Provider>
);
const { result } = renderHook(() => useTheme(), { wrapper });
expect(result.current.theme).toBe('dark');
});
```
**4. 测试自定义 Hook:**
```javascript
function useCustomHook(initialValue) {
const [value, setValue] = useState(initialValue);
const double = useMemo(() => value * 2, [value]);
return { value, setValue, double };
}
test('custom hook', () => {
const { result } = renderHook(() => useCustomHook(5));
expect(result.current.value).toBe(5);
expect(result.current.double).toBe(10);
act(() => {
result.current.setValue(10);
});
expect(result.current.double).toBe(20);
});
```
**5. 测试异步 Hook:**
```javascript
test('async hook', async () => {
const { result, waitForNextUpdate } = renderHook(() => useAsyncData());
expect(result.current.loading).toBe(true);
await waitForNextUpdate();
expect(result.current.loading).toBe(false);
expect(result.current.data).toBeDefined();
});
```
**6. 测试错误处理:**
```javascript
test('hook error handling', async () => {
const { result, waitForNextUpdate } = renderHook(() => useFetch('/invalid'));
await waitForNextUpdate();
expect(result.current.error).toBeInstanceOf(Error);
});
```
**最佳实践:**
- 使用 `renderHook` 测试 Hook
- 使用 `act` 包装状态更新
- 测试 Hook 的初始状态和更新后的状态
- 测试异步 Hook 时使用 `waitFor` 或 `waitForNextUpdate`
- 测试错误边界情况
- 保持测试简单,专注于 Hook 的行为
服务端 · 2月21日 15:57