A React component wrapper for web components and React hooks for Reactive Controllers.
npx @tessl/cli install tessl/npm-lit--react@1.0.00
# @lit/react
1
2
@lit/react provides React integration for Web Components and Reactive Controllers, enabling seamless interoperability between React applications and web components. The library offers utilities for property binding, event handling, and controller composition while maintaining type safety and following React patterns.
3
4
## Package Information
5
6
- **Package Name**: @lit/react
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install @lit/react`
10
11
## Core Imports
12
13
```typescript
14
import { createComponent } from "@lit/react";
15
import type { EventName, ReactWebComponent, WebComponentProps } from "@lit/react";
16
```
17
18
For the controller hook:
19
20
```typescript
21
import { useController } from "@lit/react/use-controller.js";
22
import type { ControllerConstructor } from "@lit/react/use-controller.js";
23
```
24
25
## Basic Usage
26
27
### Creating React Component Wrappers
28
29
```typescript
30
import * as React from 'react';
31
import { createComponent } from '@lit/react';
32
import { MyElement } from './my-element.js';
33
34
export const MyElementComponent = createComponent({
35
tagName: 'my-element',
36
elementClass: MyElement,
37
react: React,
38
events: {
39
onactivate: 'activate',
40
onchange: 'change',
41
},
42
});
43
44
// Usage in JSX
45
<MyElementComponent
46
active={isActive}
47
onactivate={(e) => setIsActive(e.active)}
48
/>
49
```
50
51
### Using Reactive Controllers
52
53
```typescript
54
import * as React from 'react';
55
import { useController } from '@lit/react/use-controller.js';
56
import { MouseController } from '@example/mouse-controller';
57
58
const useMouse = () => {
59
const controller = useController(React, (host) => new MouseController(host));
60
return controller.position;
61
};
62
63
const Component = () => {
64
const mousePosition = useMouse();
65
return <pre>x: {mousePosition.x} y: {mousePosition.y}</pre>;
66
};
67
```
68
69
## Architecture
70
71
@lit/react is built around two main integration patterns:
72
73
- **Component Wrapper Pattern**: `createComponent()` creates React components that properly bridge React props and web component properties/events
74
- **Controller Hook Pattern**: `useController()` adapts Lit's Reactive Controller lifecycle to React's hook system
75
- **Type Safety**: Full TypeScript integration with generic types for custom elements and events
76
- **Lifecycle Integration**: Proper integration with React's render lifecycle using `useLayoutEffect`
77
- **Server-Side Rendering**: Built-in support for SSR scenarios with `@lit/ssr-react`
78
79
## Capabilities
80
81
### Web Component Integration
82
83
Creates React component wrappers for custom elements with proper property binding and event handling, addressing React's default limitations with web components.
84
85
```typescript { .api }
86
/**
87
* Creates a React component for a custom element with proper property binding and event handling
88
* @param options Configuration object for the component wrapper
89
* @returns React ForwardRefExoticComponent that wraps the custom element
90
*/
91
function createComponent<I extends HTMLElement, E extends EventNames = {}>(
92
options: Options<I, E>
93
): ReactWebComponent<I, E>;
94
95
interface Options<I extends HTMLElement, E extends EventNames = {}> {
96
/** The React module, typically imported from the 'react' npm package */
97
react: typeof React;
98
/** The custom element tag name registered via customElements.define */
99
tagName: string;
100
/** The custom element class registered via customElements.define */
101
elementClass: Constructor<I>;
102
/** Object mapping React event prop names to custom element event names */
103
events?: E;
104
/** React component display name for debugging (defaults to element class name) */
105
displayName?: string;
106
}
107
108
type Constructor<T> = { new (): T };
109
type EventNames = Record<string, EventName | string>;
110
```
111
112
### Reactive Controller Integration
113
114
React hook that creates and manages Reactive Controllers using React's lifecycle, enabling controller composition and state management patterns from Lit in React components.
115
116
```typescript { .api }
117
/**
118
* Creates and stores a stateful ReactiveController instance with React lifecycle integration
119
* @param React The React module providing useState and useLayoutEffect hooks
120
* @param createController Function that creates a controller instance given a host
121
* @returns The created controller instance
122
*/
123
function useController<C extends ReactiveController>(
124
React: typeof window.React,
125
createController: (host: ReactiveControllerHost) => C
126
): C;
127
128
// ReactiveController and ReactiveControllerHost are imported from @lit/reactive-element
129
interface ReactiveController {
130
hostConnected?(): void;
131
hostDisconnected?(): void;
132
hostUpdate?(): void;
133
hostUpdated?(): void;
134
}
135
136
interface ReactiveControllerHost {
137
addController(controller: ReactiveController): void;
138
removeController(controller: ReactiveController): void;
139
requestUpdate(): void;
140
readonly updateComplete: Promise<boolean>;
141
}
142
143
type ControllerConstructor<C extends ReactiveController> = {
144
new (...args: Array<any>): C;
145
};
146
```
147
148
### Type System
149
150
Type utilities for enhanced TypeScript integration and type-safe event handling.
151
152
```typescript { .api }
153
/**
154
* Props type for web component used directly in React JSX
155
*/
156
type WebComponentProps<I extends HTMLElement> = React.DetailedHTMLProps<
157
React.HTMLAttributes<I>,
158
I
159
> & ElementProps<I>;
160
161
/**
162
* Type of the React component wrapping the web component (return type of createComponent)
163
*/
164
type ReactWebComponent<I extends HTMLElement, E extends EventNames = {}> =
165
React.ForwardRefExoticComponent<
166
ComponentProps<I, E> & React.RefAttributes<I>
167
>;
168
169
// Helper types used in the API
170
type ElementProps<I> = Partial<Omit<I, keyof HTMLElement>>;
171
172
type ComponentProps<I, E extends EventNames = {}> = Omit<
173
React.HTMLAttributes<I>,
174
keyof E | keyof ElementProps<I>
175
> & EventListeners<E> & ElementProps<I>;
176
177
type EventListeners<R extends EventNames> = {
178
[K in keyof R]?: R[K] extends EventName
179
? (e: R[K]['__eventType']) => void
180
: (e: Event) => void;
181
};
182
183
/**
184
* Type for casting event names with event types for better typing of event handler props
185
* @example
186
* events: {
187
* onfoo: 'foo' as EventName<FooEvent>,
188
* }
189
*/
190
type EventName<T extends Event = Event> = string & {
191
__eventType: T;
192
};
193
```
194
195
## Controller Host Implementation
196
197
The library includes a React-driven implementation of ReactiveControllerHost that bridges Lit's controller lifecycle with React hooks through an internal `ReactControllerHost` class that manages the controller lifecycle using React's `useState` and `useLayoutEffect` hooks.
198
199
## Event Handling
200
201
Enhanced event handling with type safety for custom element events.
202
203
**Basic Event Mapping:**
204
205
```typescript
206
const Component = createComponent({
207
tagName: 'my-element',
208
elementClass: MyElement,
209
react: React,
210
events: {
211
onchange: 'change',
212
oncustom: 'custom-event',
213
},
214
});
215
```
216
217
**Type-Safe Event Handling:**
218
219
```typescript
220
import type { EventName } from '@lit/react';
221
222
const Component = createComponent({
223
tagName: 'my-element',
224
elementClass: MyElement,
225
react: React,
226
events: {
227
onClick: 'pointerdown' as EventName<PointerEvent>,
228
onChange: 'input',
229
},
230
});
231
232
// Usage with properly typed event handlers
233
<Component
234
onClick={(e: PointerEvent) => console.log('Pointer event:', e)}
235
onChange={(e: Event) => console.log('Input event:', e)}
236
/>
237
```
238
239
## Server-Side Rendering
240
241
The library includes built-in support for server-side rendering when used with `@lit/ssr-react`:
242
243
```typescript
244
// SSR support is automatically enabled when litSsrReactEnabled is true
245
// or when React.createElement.name === 'litPatchedCreateElement'
246
```
247
248
## Error Handling
249
250
The library provides development-time warnings for potential integration issues:
251
252
- Warns when custom elements define properties that conflict with React reserved properties
253
- Handles property/attribute synchronization edge cases
254
- Provides proper cleanup for event listeners and controller lifecycle