I’m looking to write an HOC that counts and prints to the console the number of <h1/> elements in the wrapped component. For example:

const Foo: FC<{}> = ({}) => {
    return (
        <div>
            <h1>Foo</h1>
            <p>Bar</p>
        </div>
    )
}


export default countH1(Foo)

this should print 1 and then return Foo as is for rendering.

React.Children.forEach(child => {...})

seems to be about the explicit children property and not descendant html elements. How can I achieve this?

    • zamithal@programming.devOP
      link
      fedilink
      arrow-up
      1
      ·
      1 day ago

      The intent of this hoc is to generate a minimap for the wrapped component, it walks down the tree finding all h1, h2 etc components and generates a new minimap (a list of clickable links to the sections) from that data in a fragment. That fragment is then rendered.

      • brian@programming.dev
        link
        fedilink
        arrow-up
        2
        ·
        16 hours ago

        yeah there isn’t really a general purpose react way to do that.

        if order didn’t matter then you could just have a Header component that registers itself in a context but there’s no way to know where each component is relative to its siblings.

        the other way is to break out of react and just walk the dom. pass a ref to your component and use that as the root to walk. only works assuming normal react dom renderer and no portals.

        you can combine those two options too, use context for registration so you can attach extra info, then dom for position.

        there are some libs that let you walk a component tree, but they’re all focused on ssr and idk how they work in a browser. wouldn’t go this route for anything prod.

        last option is just store your content as data. have md/mdx/json/whatever files that are the content for your page, then as you parse them build up the tree. probably the most robust if it fits your use case. if you use MDX it seems like they already have some solutions

        • zamithal@programming.devOP
          link
          fedilink
          arrow-up
          1
          ·
          13 hours ago

          Unfortunate, this seems like something that should be pretty trivial on the surface but I can see why I’d need a non react solution.

          I’ll probably break out of react and walk the dom, seems like it will work best for me.

          Thanks for the help!