Sudeep Mishra
Sudeep Mishra

Reputation: 63

Adding functions to lit web components in react with typescript

I have a web component i created in lit, which takes in a function as input prop. but the function is not being triggered from the react component.

import React, { FC } from 'react';
import '@webcomponents/widgets'
declare global {
    namespace JSX {
        interface IntrinsicElements {
            'webcomponents-widgets': WidgetProps
        }
    }
}
interface WidgetProps extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> {
    var1: string,
    successCallback: Function,
}
const App = () =>{
   const onSuccessCallback = () =>{
       console.log("add some logic here");
   }
   return(<webcomponents-widgets var1="test" successCallBack={onSuccessCallback}></webcomponents-widgets>)
}

How can i trigger the function in react component? I have tried this is vue 3 and is working as expected.

Am i missing something?

Upvotes: 3

Views: 1113

Answers (2)

Augustine Kim
Augustine Kim

Reputation: 1186

As pointed out in this answer, React does not handle function props for web components properly at this time.

While it's possible to use a ref to add the function property imperatively, I would suggest the more idiomatic way of doing things in web components is to not take a function as a prop but rather have the web component dispatch an event on "success" and the consumer to write an event handler.

So the implementation of <webcomponents-widgets>, instead of calling

this.successCallBack();

would instead do

const event = new Event('success', {bubbles: true, composed: true});
this.dispatch(event);

Then, in your React component you can add the event listener.

const App = () => {
  const widgetRef = useRef();
  const onSuccessCallback = () => {
    console.log("add some logic here");
  }
  useEffect(() => {
    widgetRef.current?.addEventListener('success', onSuccessCallback);
    return () => {
      widgetRef.current?.removeEventListener('success', onSuccessCallback);
    }
  }, []);
  return(<webcomponents-widgets var1="test" ref={widgetRef}></webcomponents-widgets>);
}

The @lit-labs/react package let's you wrap the web component, turning it into a React component so you can do this kind of event handling declaratively.

Upvotes: 2

Valentin
Valentin

Reputation: 11802

React does not handle Web Components as well as other frameworks (but it is planned to be improved in the future).

What is happening here is that your successCallBack parameter gets converted to a string. You need to setup a ref on your web component and set successCallBack from a useEffect:

const App = () => {
   const widgetRef = useRef();
   const onSuccessCallback = () =>{
       console.log("add some logic here");
   }
   useEffect(() => {
      if (widgetRef.current) {
         widgetRef.current.successCallBack = onSuccessCallback;
      }
   }, []);
   return(<webcomponents-widgets var1="test" ref={widgetRef}></webcomponents-widgets>)
}

Upvotes: 1

Related Questions