5

I have a general component such as this

const Img = ({ component }) => {
  const image_ref = useRef()

  return (
  <>
    {component
      ref={image_ref}
    }
  </>
  )
}

And I want to use it with other components like these

const MyImg = () => <Img component={<MySpecificImg />} />
const MyBackImg = () => <Img component={<MySpecificBackImg />} />

Is there any way to do this?

The need is to be able to change the component that the <Img/> component calls

GWorking
  • 4,011
  • 10
  • 49
  • 90
  • You may give a try at HOC components. – ManirajSS Dec 11 '19 at 06:34
  • Take a look at [this answer](https://stackoverflow.com/a/42847399/5648954) and [this answer](https://stackoverflow.com/a/32371612/5648954) – Nick Parsons Dec 11 '19 at 06:42
  • @ManirajSS with HOC I can't use useRef or useState since the function is not a component (AFAIU) so I think I can't use it ||| I want to avoid any class-related React here – GWorking Dec 11 '19 at 07:38
  • 1
    @NickParsons Thanks :) first answer doesn't allow me to add more props to the component, so if this is true I can't use this, and second answer uses cloneElement which is something I don't like here, it has to be a simpler solution – GWorking Dec 11 '19 at 07:42
  • I understand that a HOC could do it, as said in an answer from your question https://stackoverflow.com/a/31757397/826815 so I'll answer yes, thanks for letting me know! – GWorking May 01 '20 at 17:05

1 Answers1

7

If you are passing the prop as <MySpecificBackImg />, then you are passing in a JSX element, you can render it in Img component as:

const Img = ({ element }) => {
  const image_ref = useRef()
  const elementWithRef = React.cloneElement(element, { ref: image_ref });
  return (
  <>
    {element}
  </>
  )
}

If you are passing in the component, which you can easily do from the sample:

const Img = ({ component: Component }) => {
  const image_ref = useRef()
  return (
  <>
    <Component ref={image_ref} />
  </>
  )
}

Do note that the ref in both cases is being attached to the outer element, if this is a component instance, you would have to use forwardRef to forward it to the inner DOM element.

Agney
  • 18,522
  • 7
  • 57
  • 75
  • By "passing in" you mean as children? *I'm trying to avoid the `cloneElement` and looking at HOC instead / if that's an option – GWorking Dec 11 '19 at 07:15
  • *At the end I am/I've extracted the redundant logic of the different components into a custom useHook so that now I don't need to change the component (and therefore to use cloneElement) – GWorking Dec 11 '19 at 07:55