or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

components.mdcontext.mdelement-creation.mdhooks.mdindex.mdreact-compatibility.mdrendering.md

hooks.mddocs/

0

# Hooks

1

2

Complete React hooks implementation for state management and side effects in functional components. All hooks are compatible with React hooks and follow the same rules and behavior patterns.

3

4

## Capabilities

5

6

### State Hook

7

8

Manages local state in functional components. Returns current state value and setter function.

9

10

```javascript { .api }

11

/**

12

* Manages local state in functional components

13

* @param initialState - Initial state value or function returning initial state

14

* @returns Array containing [currentState, setStateFunction]

15

*/

16

function useState(initialState);

17

```

18

19

**Usage Examples:**

20

21

```javascript

22

import { createElement, useState } from 'rax';

23

24

function Counter() {

25

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

26

const [name, setName] = useState('');

27

28

// With function initializer (for expensive computations)

29

const [expensiveValue, setExpensiveValue] = useState(() => {

30

return computeExpensiveValue();

31

});

32

33

const increment = () => setCount(count + 1);

34

const decrement = () => setCount(prevCount => prevCount - 1);

35

36

return createElement('div', null,

37

createElement('p', null, `Count: ${count}`),

38

createElement('input', {

39

value: name,

40

onChange: (e) => setName(e.target.value),

41

placeholder: 'Enter name'

42

}),

43

createElement('button', { onClick: increment }, '+'),

44

createElement('button', { onClick: decrement }, '-')

45

);

46

}

47

```

48

49

### Effect Hook

50

51

Performs side effects in functional components. Equivalent to componentDidMount, componentDidUpdate, and componentWillUnmount combined.

52

53

```javascript { .api }

54

/**

55

* Performs side effects in functional components (deferred execution)

56

* @param effect - Effect function, can return cleanup function

57

* @param inputs - Optional dependency array for effect optimization

58

*/

59

function useEffect(effect, inputs);

60

```

61

62

**Usage Examples:**

63

64

```javascript

65

import { createElement, useState, useEffect } from 'rax';

66

67

function DataFetcher({ userId }) {

68

const [user, setUser] = useState(null);

69

const [loading, setLoading] = useState(true);

70

71

// Effect with cleanup

72

useEffect(() => {

73

let cancelled = false;

74

75

async function fetchUser() {

76

try {

77

const response = await fetch(`/api/users/${userId}`);

78

const userData = await response.json();

79

if (!cancelled) {

80

setUser(userData);

81

setLoading(false);

82

}

83

} catch (error) {

84

if (!cancelled) {

85

console.error('Failed to fetch user:', error);

86

setLoading(false);

87

}

88

}

89

}

90

91

fetchUser();

92

93

// Cleanup function

94

return () => {

95

cancelled = true;

96

};

97

}, [userId]); // Re-run when userId changes

98

99

// Effect without dependencies (runs after every render)

100

useEffect(() => {

101

document.title = user ? `User: ${user.name}` : 'Loading...';

102

});

103

104

// Effect with empty dependencies (runs once on mount)

105

useEffect(() => {

106

console.log('Component mounted');

107

return () => console.log('Component unmounting');

108

}, []);

109

110

if (loading) {

111

return createElement('div', null, 'Loading user...');

112

}

113

114

return createElement('div', null,

115

createElement('h1', null, user.name),

116

createElement('p', null, user.email)

117

);

118

}

119

```

120

121

### Layout Effect Hook

122

123

Synchronous version of useEffect that fires before the browser paints. Use for DOM measurements and synchronous DOM mutations.

124

125

```javascript { .api }

126

/**

127

* Synchronous version of useEffect that fires before browser paint

128

* @param effect - Effect function, can return cleanup function

129

* @param inputs - Optional dependency array for effect optimization

130

*/

131

function useLayoutEffect(effect, inputs);

132

```

133

134

### Context Hook

135

136

Consumes context values from the nearest Provider component.

137

138

```javascript { .api }

139

/**

140

* Consumes context value from nearest Provider

141

* @param context - Context object created by createContext

142

* @returns Current context value

143

*/

144

function useContext(context);

145

```

146

147

**Usage Examples:**

148

149

```javascript

150

import { createElement, createContext, useContext, useState } from 'rax';

151

152

// Create context

153

const ThemeContext = createContext('light');

154

155

function App() {

156

const [theme, setTheme] = useState('light');

157

158

return createElement(ThemeContext.Provider, { value: theme },

159

createElement('div', null,

160

createElement(ThemeToggle, { onToggle: () => setTheme(theme === 'light' ? 'dark' : 'light') }),

161

createElement(ThemedButton)

162

)

163

);

164

}

165

166

function ThemedButton() {

167

const theme = useContext(ThemeContext);

168

169

return createElement('button', {

170

style: {

171

backgroundColor: theme === 'light' ? '#fff' : '#333',

172

color: theme === 'light' ? '#333' : '#fff'

173

}

174

}, `I'm ${theme} themed!`);

175

}

176

```

177

178

### Ref Hook

179

180

Creates a mutable ref object that persists across renders.

181

182

```javascript { .api }

183

/**

184

* Creates a mutable ref object that persists across renders

185

* @param initialValue - Initial value for the ref

186

* @returns RefObject with current property

187

*/

188

function useRef(initialValue);

189

```

190

191

**Usage Examples:**

192

193

```javascript

194

import { createElement, useRef, useEffect } from 'rax';

195

196

function FocusInput() {

197

const inputRef = useRef(null);

198

199

useEffect(() => {

200

// Focus input on mount

201

if (inputRef.current) {

202

inputRef.current.focus();

203

}

204

}, []);

205

206

const focusInput = () => {

207

if (inputRef.current) {

208

inputRef.current.focus();

209

}

210

};

211

212

return createElement('div', null,

213

createElement('input', { ref: inputRef, type: 'text' }),

214

createElement('button', { onClick: focusInput }, 'Focus Input')

215

);

216

}

217

```

218

219

### Callback Hook

220

221

Memoizes callback functions to prevent unnecessary re-renders of child components.

222

223

```javascript { .api }

224

/**

225

* Memoizes callback functions based on dependencies

226

* @param callback - Function to memoize

227

* @param inputs - Dependency array for memoization

228

* @returns Memoized callback function

229

*/

230

function useCallback(callback, inputs);

231

```

232

233

### Memo Hook

234

235

Memoizes computed values to avoid expensive calculations on every render.

236

237

```javascript { .api }

238

/**

239

* Memoizes computed values based on dependencies

240

* @param create - Function that returns the value to memoize

241

* @param inputs - Dependency array for memoization

242

* @returns Memoized value

243

*/

244

function useMemo(create, inputs);

245

```

246

247

**Usage Examples:**

248

249

```javascript

250

import { createElement, useState, useCallback, useMemo } from 'rax';

251

252

function ExpensiveCalculator({ items }) {

253

const [filter, setFilter] = useState('');

254

255

// Memoize expensive calculation

256

const expensiveValue = useMemo(() => {

257

console.log('Calculating expensive value...');

258

return items.reduce((sum, item) => sum + item.value, 0);

259

}, [items]);

260

261

// Memoize callback to prevent child re-renders

262

const handleFilterChange = useCallback((e) => {

263

setFilter(e.target.value);

264

}, []);

265

266

const filteredItems = useMemo(() => {

267

return items.filter(item =>

268

item.name.toLowerCase().includes(filter.toLowerCase())

269

);

270

}, [items, filter]);

271

272

return createElement('div', null,

273

createElement('input', {

274

value: filter,

275

onChange: handleFilterChange,

276

placeholder: 'Filter items...'

277

}),

278

createElement('p', null, `Total value: ${expensiveValue}`),

279

createElement('p', null, `Filtered items: ${filteredItems.length}`)

280

);

281

}

282

```

283

284

### Reducer Hook

285

286

Manages complex state logic with a reducer function, similar to Redux.

287

288

```javascript { .api }

289

/**

290

* Manages state with a reducer function

291

* @param reducer - Reducer function (state, action) => newState

292

* @param initialArg - Initial state or argument for init function

293

* @param init - Optional function to compute initial state

294

* @returns Array containing [currentState, dispatchFunction]

295

*/

296

function useReducer(reducer, initialArg, init);

297

```

298

299

**Usage Examples:**

300

301

```javascript

302

import { createElement, useReducer } from 'rax';

303

304

// Reducer function

305

function counterReducer(state, action) {

306

switch (action.type) {

307

case 'increment':

308

return { count: state.count + 1 };

309

case 'decrement':

310

return { count: state.count - 1 };

311

case 'reset':

312

return { count: 0 };

313

default:

314

return state;

315

}

316

}

317

318

function Counter() {

319

const [state, dispatch] = useReducer(counterReducer, { count: 0 });

320

321

return createElement('div', null,

322

createElement('p', null, `Count: ${state.count}`),

323

createElement('button', {

324

onClick: () => dispatch({ type: 'increment' })

325

}, '+'),

326

createElement('button', {

327

onClick: () => dispatch({ type: 'decrement' })

328

}, '-'),

329

createElement('button', {

330

onClick: () => dispatch({ type: 'reset' })

331

}, 'Reset')

332

);

333

}

334

```

335

336

### Imperative Handle Hook

337

338

Customizes the instance value exposed by a ref when using forwardRef.

339

340

```javascript { .api }

341

/**

342

* Customizes the instance value exposed by a ref

343

* @param ref - Ref object to customize

344

* @param create - Function that returns the instance value

345

* @param inputs - Optional dependency array

346

*/

347

function useImperativeHandle(ref, create, inputs);

348

```

349

350

**Usage Examples:**

351

352

```javascript

353

import { createElement, forwardRef, useImperativeHandle, useRef } from 'rax';

354

355

const FancyInput = forwardRef((props, ref) => {

356

const inputRef = useRef();

357

358

useImperativeHandle(ref, () => ({

359

focus() {

360

inputRef.current.focus();

361

},

362

scrollIntoView() {

363

inputRef.current.scrollIntoView();

364

},

365

getValue() {

366

return inputRef.current.value;

367

}

368

}), []);

369

370

return createElement('input', { ref: inputRef, ...props });

371

});

372

373

function App() {

374

const fancyInputRef = useRef();

375

376

const handleFocus = () => {

377

fancyInputRef.current.focus();

378

};

379

380

const handleGetValue = () => {

381

alert(fancyInputRef.current.getValue());

382

};

383

384

return createElement('div', null,

385

createElement(FancyInput, { ref: fancyInputRef }),

386

createElement('button', { onClick: handleFocus }, 'Focus'),

387

createElement('button', { onClick: handleGetValue }, 'Get Value')

388

);

389

}

390

```

391

392

## Hook Rules

393

394

All Rax hooks follow the same rules as React hooks:

395

396

1. **Only call hooks at the top level** - Don't call hooks inside loops, conditions, or nested functions

397

2. **Only call hooks from Rax functions** - Call hooks from functional components or custom hooks

398

3. **Hooks must be called in the same order** - Don't call hooks conditionally

399

400

## Types

401

402

```javascript { .api }

403

// State hook types

404

type StateUpdater<S> = (prevState: S) => S;

405

type SetStateAction<S> = S | StateUpdater<S>;

406

type StateSetter<S> = (value: SetStateAction<S>) => void;

407

408

// Effect hook types

409

type EffectCallback = () => (void | (() => void));

410

type DependencyList = ReadonlyArray<any>;

411

412

// Reducer hook types

413

type Reducer<S, A> = (prevState: S, action: A) => S;

414

type ReducerState<R> = R extends Reducer<infer S, any> ? S : never;

415

type ReducerAction<R> = R extends Reducer<any, infer A> ? A : never;

416

type Dispatch<A> = (value: A) => void;

417

418

// Ref hook types

419

interface MutableRefObject<T> {

420

current: T;

421

}

422

423

// Callback and memo hook types

424

type CallbackFunction = (...args: any[]) => any;

425

type MemoFactory<T> = () => T;

426

427

// Context hook types

428

interface Context<T> {

429

Provider: ComponentType<{ value: T; children?: any }>;

430

Consumer: ComponentType<{ children: (value: T) => any }>;

431

_contextID: string;

432

_defaultValue: T;

433

}

434

```