Search code examples
javascripthtmlreactjsweb-component

How do i pass data up from a child web component to it's direct parent element


I need to basically pass a value down to my web component, I will then do some random thing to it, now I want to pass that new value back up to my React Comnponent. How do I do that?

function MyReactcomp() {
   const [state, setState] = useState("Justin is cool");
   return (
        <div className="Wrapper">
           <customweb-component state={state} />
        </div>
    );
}

Now inside the customweb-component, I will change state to "No your not!!". How can I pass this value back up from my web component to my Rea t Copmponent? I know I can pass a function down because you can only pass strings down


Solution

  • Instead of querying for DOM, you should use React's Ref as shown below:

    function MyReactcomp() {
      const [state, setState] = useState("Justin is cool");
    
      // Hold the web component reference here
      const myWebComp = useRef();
    
      useEffect(() => {
        myWebComp.current?.addEventListener('tab-select', (event) => {
          setState(Object.keys(adminTabs[event.detail.tabIndex]));
        });
      }, []);
    
      return (
        <div className="Wrapper">
          <customweb-component ref={myWebComp} state={state} />
        </div>
      );
    }
    

    And, you if you need to observe for changes in your referenced element, then you can use plain useState to hold reference to the element:

    function MyReactcomp() {
      const [state, setState] = useState("Justin is cool");
    
      // Hold the web component reference here
      const [webComp, setWebComp] = useState(null);
    
      useEffect(() => {
        webComp?.addEventListener('tab-select', (event) => {
          setState(Object.keys(adminTabs[event.detail.tabIndex]));
        });
      }, [webComp]);
    
      return (
        <div className="Wrapper">
          <customweb-component ref={setWebComp} state={state} />
        </div>
      );
    }
    

    If you find doing this too many times, you can abstract this behavior into custom hooks. For example:

    function useWebCompProp(ref, initialValue) {
      const [state, setState] = useState(initialValue);
    
      useEffect(() => {
        ref.current?.addEventListener('onState', (event) => {
          // Update the state here
          setState(event.detail);
        });
      }, []);
    
      const setter = (newState) => {
        setState(newState);
        ref.current?.state = newState;
      };
    
      return [state, setter];
    }
    
    
    function useWebCompEvent(eventName, callback) {
    
      // Hold the web component reference here
      const myWebComp = useRef();
    
      useEffect(() => {
        myWebComp.current?.addEventListener(eventName, callback);
      }, []);
    
      return myWebComp;
    }
    
    
    function MyReactcomp() {
    
      const myWebComp = useWebCompEvent(eventName, (event) => {
        setState(Object.keys(adminTabs[event.detail.tabIndex]));
      });
    
      const [state, setState] = useWebCompProp(myWebComp, "Justin is cool");
    
      return (
        <div className="Wrapper">
          <customweb-component ref={myWebComp} />
        </div>
      );
    }