or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

act-utilities.mdasync-testing.mdcleanup-management.mderror-handling.mdhook-rendering.mdindex.mdserver-side-rendering.md

hook-rendering.mddocs/

0

# Hook Rendering

1

2

Core functionality for rendering and testing React hooks in isolation, providing a test harness that runs hooks within a proper React component context.

3

4

## Capabilities

5

6

### renderHook Function

7

8

Creates a test harness for running React hooks in isolation, returning a result container and utilities for interacting with the hook.

9

10

```typescript { .api }

11

/**

12

* Renders a React hook in a test environment

13

* @param callback - Function that calls the hook to be tested

14

* @param options - Optional configuration including initial props and wrapper component

15

* @returns RenderHookResult with current value, utilities, and async helpers

16

*/

17

function renderHook<TProps, TResult>(

18

callback: (props: TProps) => TResult,

19

options?: RenderHookOptions<TProps>

20

): RenderHookResult<TProps, TResult>;

21

22

interface RenderHookOptions<TProps> {

23

/** Initial props to pass to the hook callback */

24

initialProps?: TProps;

25

/** React component to wrap the hook (for context providers, etc.) */

26

wrapper?: React.ComponentType<TProps>;

27

}

28

29

interface RenderHookResult<TProps, TValue> {

30

/** Container holding the hook's return value and history */

31

result: RenderResult<TValue>;

32

/** Re-render the hook with new props */

33

rerender: (newProps?: TProps) => void;

34

/** Unmount the hook and cleanup resources */

35

unmount: () => void;

36

/** Wait for a condition to be true */

37

waitFor: (callback: () => boolean | void, options?: WaitForOptions) => Promise<void>;

38

/** Wait for a selected value to change */

39

waitForValueToChange: (selector: () => unknown, options?: WaitForValueToChangeOptions) => Promise<void>;

40

/** Wait for the next hook update */

41

waitForNextUpdate: (options?: WaitForNextUpdateOptions) => Promise<void>;

42

}

43

44

interface RenderResult<TValue> {

45

/** Current return value of the hook */

46

readonly current: TValue;

47

/** Array of all values returned by the hook (including errors) */

48

readonly all: Array<TValue | Error>;

49

/** Current error if the hook threw an error */

50

readonly error?: Error;

51

}

52

```

53

54

**Usage Examples:**

55

56

```typescript

57

import { renderHook } from "@testing-library/react-hooks";

58

import { useState } from "react";

59

60

// Simple hook test

61

test("renders hook without props", () => {

62

const { result } = renderHook(() => useState(0));

63

64

expect(result.current[0]).toBe(0);

65

expect(typeof result.current[1]).toBe("function");

66

});

67

68

// Hook with initial props

69

function useCounter(initialCount: number) {

70

const [count, setCount] = useState(initialCount);

71

return { count, increment: () => setCount(c => c + 1) };

72

}

73

74

test("renders hook with initial props", () => {

75

const { result } = renderHook(() => useCounter(5));

76

77

expect(result.current.count).toBe(5);

78

});

79

80

// Hook with wrapper component (for context)

81

const ThemeContext = React.createContext("light");

82

83

function useTheme() {

84

return React.useContext(ThemeContext);

85

}

86

87

test("renders hook with wrapper", () => {

88

const wrapper = ({ children }) => (

89

<ThemeContext.Provider value="dark">{children}</ThemeContext.Provider>

90

);

91

92

const { result } = renderHook(() => useTheme(), { wrapper });

93

94

expect(result.current).toBe("dark");

95

});

96

```

97

98

### Rerender Hook

99

100

Re-renders the hook with new props, useful for testing how hooks respond to prop changes.

101

102

```typescript { .api }

103

/**

104

* Re-render the hook with new props

105

* @param newProps - New props to pass to the hook callback (optional)

106

*/

107

rerender(newProps?: TProps): void;

108

```

109

110

**Usage Examples:**

111

112

```typescript

113

function useGreeting(name: string) {

114

return `Hello, ${name}!`;

115

}

116

117

test("hook responds to prop changes", () => {

118

const { result, rerender } = renderHook(

119

(props) => useGreeting(props.name),

120

{ initialProps: { name: "Alice" } }

121

);

122

123

expect(result.current).toBe("Hello, Alice!");

124

125

// Re-render with new props

126

rerender({ name: "Bob" });

127

128

expect(result.current).toBe("Hello, Bob!");

129

});

130

```

131

132

### Unmount Hook

133

134

Unmounts the hook and cleans up any associated resources.

135

136

```typescript { .api }

137

/**

138

* Unmount the hook and cleanup resources

139

*/

140

unmount(): void;

141

```

142

143

**Usage Examples:**

144

145

```typescript

146

function useInterval(callback: () => void, delay: number) {

147

React.useEffect(() => {

148

const interval = setInterval(callback, delay);

149

return () => clearInterval(interval);

150

}, [callback, delay]);

151

}

152

153

test("hook cleans up on unmount", () => {

154

const callback = jest.fn();

155

const { unmount } = renderHook(() => useInterval(callback, 100));

156

157

// Let some time pass

158

jest.advanceTimersByTime(250);

159

expect(callback).toHaveBeenCalledTimes(2);

160

161

// Unmount and verify cleanup

162

unmount();

163

jest.advanceTimersByTime(200);

164

expect(callback).toHaveBeenCalledTimes(2); // No more calls

165

});

166

```

167

168

### Result History

169

170

Access to the complete history of hook return values and errors.

171

172

```typescript { .api }

173

interface RenderResult<TValue> {

174

/** Current return value of the hook */

175

readonly current: TValue;

176

/** Array of all values returned by the hook throughout its lifecycle */

177

readonly all: Array<TValue | Error>;

178

/** Current error if the hook is in an error state */

179

readonly error?: Error;

180

}

181

```

182

183

**Usage Examples:**

184

185

```typescript

186

function useToggle(initial = false) {

187

const [value, setValue] = useState(initial);

188

const toggle = () => setValue(prev => !prev);

189

return { value, toggle };

190

}

191

192

test("tracks hook result history", () => {

193

const { result } = renderHook(() => useToggle(false));

194

195

expect(result.current.value).toBe(false);

196

expect(result.all).toHaveLength(1);

197

expect(result.all[0]).toEqual({ value: false, toggle: expect.any(Function) });

198

199

act(() => {

200

result.current.toggle();

201

});

202

203

expect(result.current.value).toBe(true);

204

expect(result.all).toHaveLength(2);

205

expect(result.all[1]).toEqual({ value: true, toggle: expect.any(Function) });

206

});

207

```