Pass ref to a custom component from visual editor

Hi @builder.io team, is there any way to pass refs to custom components?

I’ve tried creating the ref with useRef hook in the page component and pass it to BuilderComponent state prop.
I’m having errors assigning a custom ref property within the styles tab ( custom html properties ). I can’t find any other way, I also tried passing it down as prop but it didn’t work.

I’ve created a test component just for this purpose:

const RefComponent = React.forwardRef(({ attributes }, ref) => {
  return <div ref={ref} {...attributes} />
})

Builder.registerComponent(RefComponent, { name: 'RefComponent', noWrap: true, inputs: [] } )

Hi @luigiveoworld!

I am double checking with our team to see if this is possible. In the mean time, can you share more details about what you’re trying to accomplish?

Hi @maddy, I’ve ended up creating a custom component with the ref on it and passing a callback function as prop.

I wanted to run a function based on the intersection observer API.

import { useEffect, useRef, useState } from 'react'
import { Builder } from '@builder.io/react'
import { useIntersectionObserver } from '@react-hookz/web'

const SentinelComponent = ({ onIntersecting = () => {} }) => {
  const [visible, setVisible] = useState(false)
  const sentinelRef = useRef()
  const intersection = useIntersectionObserver(sentinelRef, { rootMargin: '0px' })

  useEffect(() => {
    if (typeof IntersectionObserver === 'undefined') {
      setVisible(false) // TODO: Load with button action
    } else if (intersection?.intersectionRatio > 0) {
      setVisible(true)
    }
  }, [intersection])

  useEffect(() => {
    if (visible && sentinelRef.current) {
      onIntersecting()
      setVisible(false)
    }
  }, [visible, onIntersecting])

  return <div ref={sentinelRef} />
}

Builder.registerComponent(SentinelComponent, {
  name: 'Sentinel',
  inputs: [],
})

Hello @luigiveoworld,

What you might be looking for is using our <StateProvider> component so that you can access this reference on state within the Builder Block context.

function hitHOC({ children, hits }: { children?: JSX.Element; hits: any }) {
  return <StateProvider state={{ hits }}>{children}</StateProvider>;
}

// Pass all hits back to any item
export const AlgoliaHitsWrapper = connectHits(hitHOC);

More detail here: Component with bindings from plugin - #2 by steve

I have not tried this with a ref yet, but I might be able to create an example quick.