skip to Main Content

I need to embed a Lit web component in a React application. The web component at some point will be dispatching a custom event, and I need to capture it in the React application and react accordingly.

However, for some reason I am failing to capture the event. I have very little to no experience using React, so this is making it more difficult.

so I have my <custom-web-component/> embedded in the tsx file.
Then I tried to register an event listener like below:

React.useEffect(() => {
    window.addEventListener("myCustomEvent", onCustomEvent);

    // cleanup this component
    return () => {
      window.removeEventListener("myCustomEvent", onCustomEvent);
    };
}, []);


function onCustomEvent(event: Event) {
    const customEventDetail = (event as CustomEvent).detail as EventDetail;

    console.log(customEventDetail);
}

However, when the event is triggered by the custom component, the event listener is not capturing it and hence I don’t get anything logged in the console.

2

Answers


  1. The issue is that you listen and emit in different scopes. When you emit in a web component that does not "escape" the shadowDOM. You can do a couple of things, one is just putting an event handler on a component, which with this kind of component should work out of the box. You can listen for events on that component’s shadowDOM or change event emitter config to pass through shadomDOM and be "accessible" on window.

    If you set bubbles: true, composed: true when emitting, you should be able to do what you want.

    But to be frank, with lit components. The easiest way is just to follow the documentation. What you want to achive should work out of the box as <my-lit-component onMyCustomEvent={handler} />.

    Check out docs. here https://lit.dev/docs/frameworks/react/

    Login or Signup to reply.
  2. It is not clear from your question whether the react code that you posted lives inside a component or not. So to be extra clear, Here is an example of how that react file should look like:

    import { useEffect } from "react";
    
    // This is a react component (inside your react application) that listens to the custom event that gets fired by the web component.
    const ComponentListeningToEvent = () => {
    
      // place the useEffect inside this component.
      useEffect(() => {
        // move this function iside the useEffect so you
        // don't have to add it as a dependency
        const onCustomEvent = (event: Event) => {
          const customEventDetail = (event as CustomEvent).detail as EventDetail;
    
          console.log(customEventDetail);
        }
    
        window.addEventListener("myCustomEvent", onCustomEvent);
    
        // cleanup this component
        return () => {
          window.removeEventListener("myCustomEvent", onCustomEvent);
        };
      }, []);
    
      // Your component does not have to return anything, 
      // so I left an empty fragment here.
      return <></>;
    }
    

    Then you just call the component inside your app where you want it.

    <ComponentListeningToEvent />
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search