Reputation: 1654
Ok, there's a lit web component I need to use in a React app (which is using TS/TSX).
(In case you think the naming here is odd, I'm using dummy names)
I know I can just have the web component in React like this:
<lit-web-component text="my text"></lit-web-component>
And that works, it displays the component.
However, this lit component also dispatches an event, and I need the React app to catch this.
After researching, I found that I need to use a package(@lit/react) and create a wrapper component to do this. (https://lit.dev/docs/frameworks/react/)
I'm following the documentation, but I keep getting an error with the properties on the lit component (text). It gives this error:
Type '{ text: string; }' is not assignable to type 'IntrinsicAttributes & Omit<HTMLAttributes<HTMLElement>, never> & EventListeners<{}> & Partial<Omit<HTMLElement, keyof HTMLElement>> & RefAttributes<...>'.
Property 'text' does not exist on type 'IntrinsicAttributes & Omit<HTMLAttributes<HTMLElement>, never> & EventListeners<{}> & Partial<Omit<HTMLElement, keyof HTMLElement>> & RefAttributes<...>
Here is the React wrapper component I'm creating:
export const MyElementComponent = createComponent({
tagName: 'lit-web-component',
elementClass: LitWebComponent,
react: React,
events: {
onHeaderButtonClick: 'header-button-click',
},
});
And then using it in react as: <MyElementComponent text="my text" />
And it produces the above error. I have no idea how to tell it that this wrapper needs to take in these properties.
LitWebComponent
is being imported as import { LitWebComponent } from '@my-scope/my-lit-library';
How do I declare these properties?
I hope that this issue is solvable on the React side, making changes to the lit component would be difficult.
Upvotes: 1
Views: 533
Reputation: 1186
I'll start off by saying you might not need to use @lit/react
for your use case if it's giving you trouble, and props you need to pass in are just strings.
You can use a ref to imperatively add event listeners.
const App = () => {
const ref = useRef(null);
useEffect(() => {
if (ref.current) {
const handler = (e) => { /* do stuff */ }
ref.current.addEventListener('header-button-click', handler);
return () => {
ref.current.removeEventListener('header-button-click', handler);
}
}
});
return <lit-web-component ref={ref} text="my text"></lit-web-component>;
}
A future version of React (likely 19) will add better custom element support so that you can add event listeners by prepending on
to the event name and using that as a prop.
If you still wish to use the @lit/react
wrapper,
based on the error, it seems like createComponent
is inferring the type of the provided elementClass
to be HTMLElement
, when it should be the class extending HTMLElement
, LitWebComponent
which should also have the text
property.
@lit/react
exports a ReactWebComponent
type which you could try and use it like
import {createComponent, type ReactWebComponent} from '@lit/react';
const _MyElementComponent = createComponent({
tagName: 'lit-web-component',
elementClass: LitWebComponent,
react: React,
events: {
onHeaderButtonClick: 'header-button-click',
},
});
export const MyElementComponent =
_MyElementComponent as ReactWebComponent<
LitWebComponent, {onHeaderButtonClick: 'header-button-click'}
>;
though if the type inference didn't work, I'm not sure that would work.
You can also assert the type more directly like
interface ElementProps {
text: string;
onHeaderButtonClick: (e: Event) => void;
}
export const MyElementComponent =
_MyElementComponent as React.ForwardRefExoticComponent<
React.PropsWithoutRef<ElementProps> & React.RefAttributes<LitWebComponent>
>
Upvotes: 0