Skip to content

Commit 4e75de4

Browse files
committed
New: attributeStore and useWebComponentAttribute
* allow convenient tracking of attribute changes with attributeStore and respond to updates to observedAttributes with useWebComponentAttribute
1 parent a82add6 commit 4e75de4

File tree

5 files changed

+26697
-3924
lines changed

5 files changed

+26697
-3924
lines changed

README.md

+72
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,78 @@ customElements.define('incrementer', ReactTestComponent);
6363
The key pieces of code are `... extends ReactHTMLElement` and `this.render`,
6464
which mounts our app to its designated `mountPoint`, [as described below](#thismountpoint-and-using-custom-templates).
6565

66+
### Responding to Attribute Changes
67+
68+
There are two approaches to responding to attribute updates.
69+
70+
1. this.render()
71+
2. `attributeStore.setAttribute()`
72+
73+
Calling `this.render()` in `attributeChangedCallback` is possible. As per the [react docs](beta.reactjs.org/apis/react-dom/render#updating-the-rendered-tree) it is possible to call the render function more than once on the same DOM node. It is possible to pass attributes as props this way. Please ensure you are only calling `this.render()` in `attributeChangedCallback()` while the web component is connected to the DOM.
74+
75+
```typescript
76+
import React, { useEffect } from 'react';
77+
import ReactHTMLElement from 'react-html-element';
78+
79+
const Greeting: React.FC<{ name: string }> = ({ name }) => (
80+
<div>Hello, ${name}</div>
81+
);
82+
83+
class GreetingComponent extends ReactHTMLElement {
84+
static get observedAttributes() {
85+
return ['name'];
86+
}
87+
88+
renderApp() {
89+
const name = this.getAttribute('name');
90+
this.render(<Greeting name={name} />);
91+
}
92+
93+
connectedCallback() {
94+
this.renderApp();
95+
}
96+
97+
attributeChangedCallback() {
98+
if (this.isConnected) {
99+
this.renderApp();
100+
}
101+
}
102+
}
103+
```
104+
105+
Alternatively, you may use the `attributeStore` and `useWebComponentAttribute` hook to track attribute changes and update your app accordingly.
106+
107+
```typescript
108+
import React from 'react';
109+
import ReactHTMLElement, {
110+
attributeStore,
111+
useWebComponentAttribute,
112+
} from 'react-html-element';
113+
114+
const Greeting: React.FC = () => {
115+
const name = useWebComponentAttribute('name');
116+
return <div>Hello, ${name}</div>;
117+
};
118+
119+
class GreetingComponent extends ReactHTMLElement {
120+
static get observedAttributes() {
121+
return ['name'];
122+
}
123+
124+
connectedCallback() {
125+
this.render(<Greeting />);
126+
}
127+
128+
attributeChangedCallback(
129+
name: string,
130+
oldValue: string | null,
131+
newValue: string | null
132+
) {
133+
attributeStore.setAttribute(name, newValue);
134+
}
135+
}
136+
```
137+
66138
> ### Polyfills
67139
>
68140
> One thing to remember is that you will need to load [the webcomponentsjs polyfills](https://www.webcomponents.org/polyfills) for `ReactHTMLElement` to work in all browsers.

0 commit comments

Comments
 (0)