Reputation: 51
I'm trying to use lit-element component in my React project, and I'd like to pass in the callback function to lit-element component from React but with no luck.
I've tried a couple of different ways, like change property type, and pass function in as a string, but none of them works.
lit-element component code:
import { LitElement, html } from "lit-element";
class MyButton extends LitElement {
static get properties() {
return {
clickHandler: {
type: String
},
bar: {
type: String
}
};
}
render() {
const foo = this.clickHandler; //value is undefined
const bar = this.bar; //value is "it's bar"
return html`
<button @click=${this.clickHandler}>click me</button>
`;
}
}
customElements.define("my-button", MyButton);
react side code:
<my-button clickHandler={() => alert("clicked")} bar="it's bar" />
I put a break point in the render section of the component, and I can see the 'bar' value get passed in correctly, but the value of 'clickHandler' is undefined.
Does anyone have any idea on how to pass function from React to lit-element?
Thanks!
Upvotes: 5
Views: 5935
Reputation: 7671
This question probably isn't just valid for react. It's quite general, how do I pass a handler from parent to child component, either it's a lit-element or html element.
According to the property doc, https://lit-element.polymer-project.org/guide/properties
<my-element
mystring="hello world"
mynumber="5"
mybool
myobj='{"stuff":"hi"}'
myarray='[1,2,3,4]'>
</my-element>
Doesn't seem that it supports (callback) function at the moment. So how does Element handle event from parent level ?
According to the event doc, https://lit-element.polymer-project.org/guide/events, you can dispatch any event to the dom tree, including your parent. Dom
event system is much broader than React
prop system.
class MyElement extends LitElement {
...
let event = new CustomEvent('my-event', {
detail: {
message: 'Something important happened'
}
});
this.dispatchEvent(event);
}
and then in either lit or non-lit context, use the following to handle the event,
const myElement = document.querySelector('my-element');
myElement.addEventListener('my-event', (e) => {console.log(e)});
This way you can allow children to fire implementation for parent, which is exactly the definition for callback.
Upvotes: 5
Reputation: 6104
What I found that works is adding a ref in the react component to the lit element, then literally setting the property on it.
So, for the following JSX:
<some-webcomponent ref={this.myRef}></some-webcomponent>
You can pass a property to ‘some-webcomponent’ in i.e. componentDidMount:
componentDidMount () {
const element = this.myRef.current;
element.someCallback = () => // ...
}
It’s not too pretty, but I wouldn’t consider it a hack either. Requires quite a lot of boilerplate though :/
Here’s a full React component for reference:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return <some-webcomponent ref={this.myRef}></some-webcomponent>;
}
componentDidMount() {
const element = this.myRef.current;
element.someCallback = () => console.log(“call!”);
}
}
Where the lit element is:
import { LitElement, html } from "lit-element";
class SomeWebcomponent extends LitElement {
static get properties() {
return {
someCallback: { type: Function }
};
}
render() {
return html`
<button @click=${this.someCallback}>click me</button>
`;
}
}
customElements.define("some-webcomponent", SomeWebcomponent);
Upvotes: 1
Reputation: 9
Have a look at the menu button click function for the no redux pwa-starter-kit at https://github.com/Polymer/pwa-starter-kit/blob/template-no-redux/src/components/my-app.js. I believe that provides the example that may work for you.
Upvotes: 0