Making a react component aware of host app changes?

How do I make a react component aware of host app changes?
A basic example I’ve been trying:

import React, { useEffect } from "react";
import { app } from "indesign";
export const DocName = () => {
  let doc = app.activeDocument;
  useEffect(() => { console.log(doc.name) }, [doc]);
  return  <sp-heading>{doc.name}</sp-heading>;
};
  1. useState to bring variables under React’s control
  2. Register InDesign event listeners to capture host app changes
  3. Remove event listeners when no longer needed
import React, { useEffect, useState } from 'react' ;
import InDesign from 'indesign' ;
const { app, Event } = InDesign ;

export const DocName = () => {
  const [docname, setDocname] = useState('') ;
  
  const handleContextChanged = (event) => {
    const doc = app.activeDocument ;
    if(doc) {
      const currentName = doc.name ;
      console.log(currentName) ;
      if(currentName !== docname) {
        setDocname(currentName) ;
      }
    }
  } ;

  // add events on componentDidMount
  useEffect(() => {
    app.addEventListener(Event.AFTER_CONTEXT_CHANGED, handleContextChanged) ;
    
    return () => {
      // remove events on componentDidUnmount
      app.removeEventListener(Event.AFTER_CONTEXT_CHANGED, handleContextChanged) ;
    } ;
  }, []) ;
  
  return (
    <sp-heading>{docname}</sp-heading>
  ) ;
}

Many thanks for that.
I was hoping I could do away with the native events, as the host DOM is a direct part of the application. Particularly since there are a lot of things in InDesign that will not trigger events, like changes to the paragraph styles. I’ve used setInterval to pool ID for changes:

import React, { useEffect, useState } from 'react';
import { app } from 'indesign';
console.log(app.scriptPreferences.version);
export const Test = () => {
  const [doc, setDoc] = useState(app.documents.item(0));

  const [styles, setStyles] = useState(
    doc.isValid ? doc.allParagraphStyles : []
  );
  useEffect(() => {
    const intv = setInterval(() => {
      setDoc(app.documents.item(0));
      setStyles(doc.isValid ? doc.allParagraphStyles : []);
    }, 500);
    return () => clearInterval(intv);
  });
  return (
    <>
      <sp-heading>{doc.isValid ? doc.name : '[no document open]'}</sp-heading>
      {doc.isValid ? (
        <sp-menu>
          {styles.map((st) => {
            return <sp-menu-item key={st.id}>{st.name}</sp-menu-item>;
          })}
        </sp-menu>
      ) : (
        <></>
      )}
    </>
  );
};

Is that horrible? Sorry, I’m a react noob.
Also, I must confess my complete ignorance on the AFTER_CONTEXT_CHANGED event. What does it actually do? When is it triggered? The documentation only mentions Dispatched after the active context changes. This event bubbles. This event is not cancelable. What is the active context? I never used that event before.

After all, InDesign features are handled within InDesign, and they remain the same even with UXP.

If there is no other option but to use setInterval, then there’s no choice but to do so. It seems like it might also be achievable with AFTER_UPDATE or similar events, but you are probably more knowledgeable about that than I am.

It appears that AFTER_CONTEXT_CHANGED is triggered when the focus of the document is changed.