or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

app-container.mdbuild-integration.mdcomponent-utilities.mdconfiguration.mdhot-wrapper.mdindex.md

component-utilities.mddocs/

0

# Component Utilities

1

2

React Hot Loader provides utility functions for component comparison, cold component marking, and hot reload control. These utilities help manage component hot reloading behavior and provide fine-grained control over the hot reload process.

3

4

## Capabilities

5

6

### Component Comparison

7

8

Tests whether two React component types are equal, taking into account proxy components used by hot reloading.

9

10

```typescript { .api }

11

/**

12

* Tests if types of two components are equal

13

* @param typeA - First component type

14

* @param typeB - Second component type

15

* @returns true if components are equal (considering hot reload proxies)

16

*/

17

function areComponentsEqual<T>(typeA: React.ComponentType<T>, typeB: React.ComponentType<T>): boolean;

18

```

19

20

**Usage Examples:**

21

22

```javascript

23

import { areComponentsEqual } from 'react-hot-loader';

24

25

const ComponentA = () => <div>A</div>;

26

const ComponentB = () => <div>B</div>;

27

28

// Basic comparison

29

console.log(areComponentsEqual(ComponentA, ComponentA)); // true

30

console.log(areComponentsEqual(ComponentA, ComponentB)); // false

31

32

// Hot reload scenario

33

const OriginalComponent = () => <div>Original</div>;

34

// After hot reload, component reference changes but areComponentsEqual

35

// will return true if it's the same logical component

36

const hotReloadedComponent = () => <div>Updated</div>;

37

38

// This accounts for hot reload proxies

39

console.log(areComponentsEqual(OriginalComponent, hotReloadedComponent));

40

// May return true if they're the same component after hot reload

41

```

42

43

```typescript

44

// TypeScript usage with generic types

45

interface Props {

46

name: string;

47

}

48

49

const UserComponent: React.FC<Props> = ({ name }) => <div>{name}</div>;

50

const AdminComponent: React.FC<Props> = ({ name }) => <div>Admin: {name}</div>;

51

52

const isSameComponent = areComponentsEqual(UserComponent, AdminComponent);

53

console.log(isSameComponent); // false

54

```

55

56

```javascript

57

// Testing in component lifecycle

58

class MyComponent extends React.Component {

59

shouldComponentUpdate(nextProps) {

60

// Check if the component type has changed due to hot reload

61

return !areComponentsEqual(this.constructor, nextProps.componentType);

62

}

63

64

render() {

65

return <div>My Component</div>;

66

}

67

}

68

```

69

70

### Cold Component Marking

71

72

Marks a component as "cold", making it invisible to React Hot Loader. Changes to cold components will cause local state loss and full re-mounting.

73

74

```typescript { .api }

75

/**

76

* Marks component as cold, making it invisible for React-Hot-Loader

77

* Any changes to that component will cause local state loss

78

* @param component - Component to mark as cold

79

* @returns The same component (unchanged)

80

*/

81

function cold<T = React.ComponentType<any>>(component: T): T;

82

```

83

84

**Usage Examples:**

85

86

```javascript

87

import React from 'react';

88

import { cold } from 'react-hot-loader';

89

90

// Mark a component as cold

91

const StaticComponent = cold(() => {

92

return <div>This component won't hot reload</div>;

93

});

94

95

export default StaticComponent;

96

// Changes to this component will cause full re-mount, losing state

97

```

98

99

```javascript

100

// Cold class component

101

import { cold } from 'react-hot-loader';

102

103

class DatabaseConnection extends React.Component {

104

constructor(props) {

105

super(props);

106

this.connection = establishConnection();

107

}

108

109

componentWillUnmount() {

110

this.connection.close();

111

}

112

113

render() {

114

return <div>Connected to database</div>;

115

}

116

}

117

118

// Mark as cold to prevent hot reload interference with database connection

119

export default cold(DatabaseConnection);

120

```

121

122

```typescript

123

// TypeScript cold component

124

import { cold } from 'react-hot-loader';

125

126

interface CriticalProps {

127

securityToken: string;

128

}

129

130

const SecurityComponent: React.FC<CriticalProps> = ({ securityToken }) => {

131

// This component handles sensitive operations

132

return <div>Secure Area</div>;

133

};

134

135

// Mark as cold for security reasons - always full reload

136

export default cold(SecurityComponent);

137

```

138

139

```javascript

140

// Conditional cold marking

141

import { cold } from 'react-hot-loader';

142

143

const MyComponent = () => <div>My Component</div>;

144

145

// Only mark as cold in certain conditions

146

const shouldBeCold = process.env.DISABLE_HOT_RELOAD === 'true';

147

const ExportedComponent = shouldBeCold ? cold(MyComponent) : MyComponent;

148

149

export default ExportedComponent;

150

```

151

152

## Advanced Usage Patterns

153

154

### Selective Hot Reloading

155

156

```javascript

157

import { hot, cold } from 'react-hot-loader';

158

159

// Hot reload for UI components

160

const UIComponent = hot(module)(() => <div>UI Component</div>);

161

162

// Cold for critical system components

163

const SystemComponent = cold(() => <div>System Component</div>);

164

165

// Mixed usage in app

166

const App = () => (

167

<div>

168

<UIComponent /> {/* Will hot reload and preserve state */}

169

<SystemComponent /> {/* Will full reload and reset state */}

170

</div>

171

);

172

173

export default hot(module)(App);

174

```

175

176

### Component Comparison in Testing

177

178

```javascript

179

import { areComponentsEqual } from 'react-hot-loader';

180

import { render } from '@testing-library/react';

181

182

describe('Component equality', () => {

183

it('should recognize same components', () => {

184

const ComponentA = () => <div>Test</div>;

185

const ComponentB = () => <div>Test</div>;

186

187

// In testing, these are different functions

188

expect(areComponentsEqual(ComponentA, ComponentA)).toBe(true);

189

expect(areComponentsEqual(ComponentA, ComponentB)).toBe(false);

190

});

191

192

it('should handle hot reloaded components', () => {

193

// Mock hot reload scenario

194

const originalComponent = () => <div>Original</div>;

195

196

// Simulate hot reload by creating new component with same "identity"

197

const reloadedComponent = () => <div>Reloaded</div>;

198

199

// In actual hot reload, these would be considered equal

200

// Test your specific hot reload logic here

201

});

202

});

203

```

204

205

### Error Boundary with Cold Components

206

207

```javascript

208

import React from 'react';

209

import { cold } from 'react-hot-loader';

210

211

// Error boundary should be cold to prevent hot reload issues

212

class ErrorBoundary extends React.Component {

213

constructor(props) {

214

super(props);

215

this.state = { hasError: false };

216

}

217

218

static getDerivedStateFromError(error) {

219

return { hasError: true };

220

}

221

222

componentDidCatch(error, errorInfo) {

223

console.error('Error caught by boundary:', error, errorInfo);

224

}

225

226

render() {

227

if (this.state.hasError) {

228

return <div>Something went wrong.</div>;

229

}

230

231

return this.props.children;

232

}

233

}

234

235

// Mark error boundary as cold for reliability

236

export default cold(ErrorBoundary);

237

```

238

239

### Third-Party Component Integration

240

241

```javascript

242

import { cold } from 'react-hot-loader';

243

import SomeThirdPartyComponent from 'some-library';

244

245

// Third-party components often don't work well with hot reload

246

const SafeThirdPartyComponent = cold(SomeThirdPartyComponent);

247

248

// Wrapper component can still be hot

249

const MyWrapper = ({ data }) => (

250

<div>

251

<h1>My App</h1>

252

<SafeThirdPartyComponent data={data} />

253

</div>

254

);

255

256

export default hot(module)(MyWrapper);

257

```

258

259

## Performance Considerations

260

261

### When to Use Cold Components

262

263

```javascript

264

// ✅ Good candidates for cold():

265

// - Components with complex initialization

266

// - Components that manage external resources

267

// - Third-party components

268

// - Error boundaries

269

// - Components with side effects in constructor

270

271

// ❌ Avoid cold() for:

272

// - Simple presentational components

273

// - Components you frequently modify

274

// - Components where state preservation is important

275

```

276

277

### Component Comparison Performance

278

279

```javascript

280

// areComponentsEqual() is lightweight but consider caching for heavy usage

281

const componentComparison = useMemo(() => {

282

return areComponentsEqual(ComponentA, ComponentB);

283

}, [ComponentA, ComponentB]);

284

```

285

286

## Debugging Component Issues

287

288

```javascript

289

import { areComponentsEqual, cold } from 'react-hot-loader';

290

291

const DebugComponent = ({ children }) => {

292

useEffect(() => {

293

// Debug component equality issues

294

console.log('Component equality check:',

295

areComponentsEqual(children.type, children.type)

296

);

297

}, [children]);

298

299

return children;

300

};

301

302

// Use cold for debugging to avoid hot reload interference

303

export default cold(DebugComponent);

304

```

305

306

## Migration Notes

307

308

### Legacy Component Comparison

309

310

```javascript

311

// Old way (manual proxy checking)

312

const getActualComponent = (component) => {

313

return component.__hotReloadProxy ?

314

component.__hotReloadProxy.getCurrent() :

315

component;

316

};

317

318

const manualComparison = (a, b) => {

319

return getActualComponent(a) === getActualComponent(b);

320

};

321

322

// New way (recommended)

323

import { areComponentsEqual } from 'react-hot-loader';

324

const modernComparison = areComponentsEqual(a, b);

325

```

326

327

### Component Configuration

328

329

Sets specific options for individual components, providing fine-grained control over hot reload behavior for specific components.

330

331

```typescript { .api }

332

/**

333

* Configure options for a specific component

334

* @param component - Component to configure

335

* @param options - Configuration options for the component

336

* @returns Configured component

337

*/

338

function configureComponent(component: React.ComponentType<any>, options: any): React.ComponentType<any>;

339

```

340

341

**Usage Examples:**

342

343

```javascript

344

import { configureComponent } from 'react-hot-loader';

345

346

const MyComponent = () => <div>My Component</div>;

347

348

// Configure component with specific options

349

const ConfiguredComponent = configureComponent(MyComponent, {

350

pureSFC: true,

351

pureRender: false

352

});

353

354

export default ConfiguredComponent;

355

```

356

357

```javascript

358

// Configure multiple components differently

359

const FastComponent = configureComponent(ComponentA, {

360

pureSFC: true,

361

pureRender: true

362

});

363

364

const RichComponent = configureComponent(ComponentB, {

365

pureSFC: false,

366

allowSFC: true

367

});

368

```

369

370

### Cold Component Best Practices

371

372

```javascript

373

// ✅ Good: Export cold components directly

374

export default cold(MyComponent);

375

376

// ✅ Good: Conditional cold based on environment

377

export default process.env.NODE_ENV === 'test'

378

? cold(MyComponent)

379

: hot(module)(MyComponent);

380

381

// ❌ Avoid: Mixing hot and cold on same component

382

const Component = hot(module)(cold(MyComponent)); // Don't do this

383

384

// ❌ Avoid: Cold inside render methods

385

const BadExample = () => {

386

const ColdComponent = cold(SomeComponent); // Don't do this

387

return <ColdComponent />;

388

};

389

```