Skip to content

Commit fff10ad

Browse files
committed
Add more information about event and property binding on custom elements
1 parent e9a7cb1 commit fff10ad

File tree

1 file changed

+84
-10
lines changed
  • src/content/reference/react-dom/components

1 file changed

+84
-10
lines changed

src/content/reference/react-dom/components/index.md

Lines changed: 84 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -162,23 +162,97 @@ Similar to the [DOM standard,](https://developer.mozilla.org/en-US/docs/Web/API/
162162

163163
### Custom HTML elements {/*custom-html-elements*/}
164164

165-
If you render a tag with a dash, like `<my-element>`, React will assume you want to render a [custom HTML element.](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) In React, rendering custom elements works differently from rendering built-in browser tags:
166-
167-
- All custom element props are serialized to strings and are always set using attributes.
168-
- Custom elements accept `class` rather than `className`, and `for` rather than `htmlFor`.
165+
If you render a tag with a dash, like `<my-element>`, React will assume you want to render a [custom HTML element.](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements)
169166

170167
If you render a built-in browser HTML element with an [`is`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/is) attribute, it will also be treated as a custom element.
171168

172-
<Note>
169+
#### Setting values on custom elements {/*attributes-vs-properties*/}
170+
171+
Custom elements have two methods of passing data into them:
172+
173+
1) Attributes: Which are displayed in markup and can only be set to string values
174+
2) Properties: Which are not displayed in markup and can be set to arbitrary JavaScript values
175+
176+
By default, React will pass values bound in JSX as attributes:
177+
178+
```jsx
179+
<my-element value="Hello, world!"></my-element>
180+
```
181+
182+
Non-string JavaScript values passed to custom elements will be serialized by default:
183+
184+
```jsx
185+
// Will be passed as `"1,2,3"` as the output of `[1,2,3].toString()`
186+
<my-element value={[1,2,3]}></my-element>
187+
```
188+
189+
React will, however, recognize an custom element's property as one that it may pass arbitrary values to if the property name shows up on the class during construction:
190+
191+
```javascript {4-6}
192+
class MyElement extends HTMLElement {
193+
constructor() {
194+
super();
195+
// The value here will be overwritten by React
196+
// when initialized as an element
197+
this.value = undefined;
198+
}
173199

174-
[A future version of React will include more comprehensive support for custom elements.](https://github.com/facebook/react/issues/11347#issuecomment-1122275286)
200+
connectedCallback() {
201+
this.innerHTML = this.value.join(", ");
202+
}
203+
}
204+
```
175205

176-
You can try it by upgrading React packages to the most recent experimental version:
206+
#### Listening for events on custom elements {/*custom-element-events*/}
207+
208+
A common pattern when using custom elements is that they may dispatch [`CustomEvent`s](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent) rather than accept a function to call when an event occur:
209+
210+
```javascript {8-15}
211+
class MyElement extends HTMLElement {
212+
constructor() {
213+
super();
214+
this.test = undefined;
215+
this.emitEvent = this._emitEvent.bind(this);
216+
}
217+
218+
_emitEvent() {
219+
const event = new CustomEvent('speak', {
220+
detail: {
221+
message: 'Hello, world!',
222+
},
223+
});
224+
this.dispatchEvent(event);
225+
}
226+
227+
connectedCallback() {
228+
this.el = document.createElement('button');
229+
this.el.innerText = 'Say hi';
230+
this.el.addEventListener('click', this.emitEvent);
231+
this.appendChild(this.el);
232+
}
233+
234+
disconnectedCallback() {
235+
this.el.removeEventListener('click', this.emitEvent);
236+
}
237+
}
238+
```
239+
240+
You can listen for these events using an `on` prefix when binding to the event via JSX:
241+
242+
```jsx
243+
<my-element onspeak={e => console.log(e.detail.message)}></my-element>
244+
```
245+
246+
<Note>
177247

178-
- `react@experimental`
179-
- `react-dom@experimental`
248+
Events are case-sensative and support dashes (`-`). Preserve the casing of the event and include all dashes when listening for custom element's events:
180249

181-
Experimental versions of React may contain bugs. Don't use them in production.
250+
```jsx
251+
// Listens for `say-hi` events
252+
<my-element onsay-hi={console.log}></my-element>
253+
// Listens for `sayHi` events
254+
<my-element onsayHi={console.log}></my-element>
255+
```
182256

183257
</Note>
184258
---

0 commit comments

Comments
 (0)