react-web-component
react-web-component copied to clipboard
Passing props in html page
Hello,
I confirm that i have the same issue. If I pass prop (ie name="Bob") in the html page, this.props is empty ....
I am using Google Chrome on Windows
Regards
Darn, I was hoping it was just me, it quick look at the source code seems that it extracts props from appInstance.props = extractAttributes(webComponentInstance);
but if useShadowDom is true it reassigns webComponentInstance to shadowRoot. // Re-assign the webComponentInstance (this) to the newly created shadowRoot webComponentInstance = webComponentInstance.createShadowRoot();
So, as a workaround you can disable shadowRoot. ReactWebComponent.create(<App />, 'my-component', false);
I then ran into the issue that props didn't seem to be set on the first render as it seems the render happens before webComponentConstructed where they get set... so I came up with the following quick hack:
webComponentConstructed(el) {
// props is updated parsed by react-web-component just before invoking this method
// but react doesn't detect this change to props so copy it to state and use state instead.
this.setState(this.props);
}
After digging deeper I decided to implement the following instead of using this library.
It doesn't have the style stuff and seems to work for me so far but your mileage may vary:
function defineElement(Component, elementName, observedAttributes) {
class CustomElement extends HTMLElement {
connectedCallback() {
const customElement = this;
const shadowRoot = this.attachShadow({mode: 'open'});
const props = [...this.attributes].reduce((props, attribute) => ({...props, [attribute.name]: attribute.value }),
{customElement, shadowRoot});
const instance =(<Component {...(props)}/>);
ReactDOM.render(instance, shadowRoot);
this.instance = instance;
this.props = props;
}
attributeChangedCallback(name, oldValue, newValue) {
const { shadowRoot, instance, props } = this;
if(!instance) return;
const newProps = {...(this.props), ...({[name]: newValue})};
const newInstance =(<Component {...(newProps)}/>);
ReactDOM.render(newInstance, shadowRoot);
this.instance = newInstance;
this.props = newProps;
}
}
CustomElement.observedAttributes = observedAttributes;
window.customElements.define(elementName, CustomElement);
}
const HelloWorld = (props) => {
const onclick = () => {
props.customElement.dispatchEvent(new CustomEvent('die'));
}
return (<h1>{props.greet || "Hi"}, {props.name || "World"}!
<button onClick={onclick}>Die!</button>
</h1>);
}
defineElement(HelloWorld, 'hello-world', ['greet', 'name']);
const hello = document.createElement("hello-world");
hello.setAttribute("name", "Visitor");
hello.addEventListener("die", () => {
hello.setAttribute("greet", "Goodbye");
});
document.body.appendChild(hello);
I think this is similar to the issue #7.