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

context.mddocs/

0

# Context API

1

2

React-compatible context system for managing and sharing state across component trees without prop drilling. Enables efficient data flow from parent components to deeply nested children.

3

4

## Capabilities

5

6

### Create Context

7

8

Creates a context object containing Provider and Consumer components for sharing data across component trees.

9

10

```javascript { .api }

11

/**

12

* Creates a context object for sharing data across component trees

13

* @param defaultValue - Default value used when no Provider is found in tree

14

* @returns Context object with Provider, Consumer, and internal properties

15

*/

16

function createContext(defaultValue);

17

```

18

19

The returned context object has the following structure:

20

21

```javascript { .api }

22

interface ContextObject<T> {

23

/**

24

* Provider component that supplies context value to child components

25

*/

26

Provider: ComponentClass<ProviderProps<T>>;

27

28

/**

29

* Consumer component that receives context value via render prop

30

*/

31

Consumer: ComponentClass<ConsumerProps<T>>;

32

33

/**

34

* Internal context identifier (used by Rax internally)

35

*/

36

_contextID: string;

37

38

/**

39

* Default value for the context (used by Rax internally)

40

*/

41

_defaultValue: T;

42

43

/**

44

* Internal method for finding nearest provider (used by Rax internally)

45

*/

46

__getNearestParentProvider: Function;

47

}

48

49

interface ProviderProps<T> {

50

value: T;

51

children?: any;

52

}

53

54

interface ConsumerProps<T> {

55

children: (value: T) => any;

56

}

57

```

58

59

**Usage Examples:**

60

61

```javascript

62

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

63

64

// Create context with default value

65

const ThemeContext = createContext('light');

66

const UserContext = createContext(null);

67

68

// Theme Provider Component

69

function ThemeProvider({ children }) {

70

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

71

72

const toggleTheme = () => {

73

setTheme(prevTheme => prevTheme === 'light' ? 'dark' : 'light');

74

};

75

76

const contextValue = {

77

theme,

78

toggleTheme

79

};

80

81

return createElement(ThemeContext.Provider, { value: contextValue }, children);

82

}

83

84

// User Provider Component

85

function UserProvider({ children }) {

86

const [user, setUser] = useState({ name: 'John Doe', id: 1 });

87

88

return createElement(UserContext.Provider, { value: { user, setUser } }, children);

89

}

90

91

// App with multiple providers

92

function App() {

93

return createElement(ThemeProvider, null,

94

createElement(UserProvider, null,

95

createElement(Dashboard)

96

)

97

);

98

}

99

```

100

101

### Provider Component

102

103

The Provider component supplies the context value to all descendant components. Components that consume the context will re-render when the Provider's value changes.

104

105

**Provider Usage Examples:**

106

107

```javascript

108

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

109

110

const AppContext = createContext();

111

112

function AppProvider({ children }) {

113

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

114

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

115

const [notifications, setNotifications] = useState([]);

116

117

// Context value object

118

const contextValue = {

119

user,

120

setUser,

121

theme,

122

setTheme,

123

notifications,

124

setNotifications,

125

// Helper methods

126

addNotification: (notification) => {

127

setNotifications(prev => [...prev, { ...notification, id: Date.now() }]);

128

},

129

removeNotification: (id) => {

130

setNotifications(prev => prev.filter(n => n.id !== id));

131

}

132

};

133

134

return createElement(AppContext.Provider, { value: contextValue }, children);

135

}

136

137

// Nested providers for different concerns

138

function App() {

139

return createElement(AppProvider, null,

140

createElement('div', { className: 'app' },

141

createElement(Header),

142

createElement(MainContent),

143

createElement(Footer)

144

)

145

);

146

}

147

```

148

149

### Consumer Component

150

151

The Consumer component uses a render prop pattern to access the context value. The child function receives the current context value as its argument.

152

153

**Consumer Usage Examples:**

154

155

```javascript

156

import { createElement } from 'rax';

157

158

// Using Consumer with render prop

159

function ThemedButton() {

160

return createElement(ThemeContext.Consumer, null, (themeContext) => {

161

if (!themeContext) {

162

return createElement('button', null, 'No theme available');

163

}

164

165

return createElement('button', {

166

style: {

167

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

168

color: themeContext.theme === 'light' ? '#333' : '#fff',

169

border: `1px solid ${themeContext.theme === 'light' ? '#ccc' : '#666'}`

170

},

171

onClick: themeContext.toggleTheme

172

}, `Switch to ${themeContext.theme === 'light' ? 'dark' : 'light'} mode`);

173

});

174

}

175

176

// Multiple context consumers

177

function UserProfile() {

178

return createElement(UserContext.Consumer, null, (userContext) =>

179

createElement(ThemeContext.Consumer, null, (themeContext) => {

180

if (!userContext.user) {

181

return createElement('div', null, 'Please log in');

182

}

183

184

return createElement('div', {

185

className: `user-profile ${themeContext.theme}`

186

},

187

createElement('h2', null, userContext.user.name),

188

createElement('p', null, `ID: ${userContext.user.id}`),

189

createElement('button', {

190

onClick: () => userContext.setUser(null)

191

}, 'Logout')

192

);

193

})

194

);

195

}

196

```

197

198

### Context with Hooks

199

200

The recommended modern approach is to use `useContext` hook instead of Consumer components for cleaner code.

201

202

**Hook-based Context Usage:**

203

204

```javascript

205

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

206

207

const AuthContext = createContext();

208

209

// Custom hook for easier context consumption

210

function useAuth() {

211

const context = useContext(AuthContext);

212

if (!context) {

213

throw new Error('useAuth must be used within an AuthProvider');

214

}

215

return context;

216

}

217

218

function AuthProvider({ children }) {

219

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

220

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

221

222

const login = async (email, password) => {

223

setLoading(true);

224

try {

225

const response = await fetch('/api/login', {

226

method: 'POST',

227

headers: { 'Content-Type': 'application/json' },

228

body: JSON.stringify({ email, password })

229

});

230

const userData = await response.json();

231

setUser(userData);

232

} catch (error) {

233

console.error('Login failed:', error);

234

} finally {

235

setLoading(false);

236

}

237

};

238

239

const logout = () => {

240

setUser(null);

241

};

242

243

const value = {

244

user,

245

loading,

246

login,

247

logout,

248

isAuthenticated: !!user

249

};

250

251

return createElement(AuthContext.Provider, { value }, children);

252

}

253

254

// Components using the custom hook

255

function LoginButton() {

256

const { login, loading, isAuthenticated } = useAuth();

257

258

if (isAuthenticated) {

259

return createElement('span', null, 'Already logged in');

260

}

261

262

const handleLogin = () => {

263

login('user@example.com', 'password');

264

};

265

266

return createElement('button', {

267

onClick: handleLogin,

268

disabled: loading

269

}, loading ? 'Logging in...' : 'Login');

270

}

271

272

function UserGreeting() {

273

const { user, logout } = useAuth();

274

275

if (!user) {

276

return createElement('div', null, 'Please log in');

277

}

278

279

return createElement('div', null,

280

createElement('p', null, `Welcome, ${user.name}!`),

281

createElement('button', { onClick: logout }, 'Logout')

282

);

283

}

284

```

285

286

### Context Best Practices

287

288

**Performance Optimization:**

289

290

```javascript

291

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

292

293

const AppContext = createContext();

294

295

function AppProvider({ children }) {

296

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

297

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

298

299

// Memoize context value to prevent unnecessary re-renders

300

const contextValue = useMemo(() => ({

301

user,

302

setUser,

303

theme,

304

setTheme

305

}), [user, theme]);

306

307

return createElement(AppContext.Provider, { value: contextValue }, children);

308

}

309

310

// Split contexts by concern to minimize re-renders

311

const UserContext = createContext();

312

const ThemeContext = createContext();

313

314

function UserProvider({ children }) {

315

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

316

317

const value = useMemo(() => ({ user, setUser }), [user]);

318

319

return createElement(UserContext.Provider, { value }, children);

320

}

321

322

function ThemeProvider({ children }) {

323

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

324

325

const value = useMemo(() => ({ theme, setTheme }), [theme]);

326

327

return createElement(ThemeContext.Provider, { value }, children);

328

}

329

```

330

331

## Types

332

333

```javascript { .api }

334

// Context object type

335

interface Context<T> {

336

Provider: ComponentType<ProviderProps<T>>;

337

Consumer: ComponentType<ConsumerProps<T>>;

338

_contextID: string;

339

_defaultValue: T;

340

__getNearestParentProvider: Function;

341

}

342

343

// Provider component props

344

interface ProviderProps<T> {

345

value: T;

346

children?: RaxNode;

347

}

348

349

// Consumer component props

350

interface ConsumerProps<T> {

351

children: (value: T) => RaxNode;

352

}

353

354

// Context value type helper

355

type ContextType<C extends Context<any>> = C extends Context<infer T> ? T : never;

356

357

// Custom hook return type

358

interface UseContextReturn<T> {

359

(context: Context<T>): T;

360

}

361

```