szeryf
szeryf

Reputation: 3387

React v16 – pass ref from child to parent through a wrapper component

I have an existing component hierarchy that looks like this:

const Parent = props => {
  const divElement = useRef()
  // do something with divElement
  return <Child ref={divElement} {...some props} />
}

const Child = React.forwardRef((props, ref) => {
  return <div ref={ref}><some stuff here></div>
}

This is all fine, but now I need to conditionally add a wrapper component, which wraps the <Child> component to add some special case props.

Basically what I want is something like this:

const Parent = props => {
  const divElement = useRef()
  // do something with divElement
  return someCondition ? <Wrapper {...some props} /> : <Child ref={divElement} {...some props} />
}

const Wrapper = props => {
  return <Child {...different props} />
}

const Child = React.forwardRef((props, ref) => {
  return <div ref={ref}><some stuff here></div>
}

I'm stuck on how to pass the ref from Child through the Wrapper back to Parent, so the Parent can access the Child's ref no matter whether the Wrapper is there or not...

Upvotes: 1

Views: 2395

Answers (2)

Adam C.
Adam C.

Reputation: 462

In addition to using React.forwardRef like @Reductio said, you could use custom props to pass down the ref to the children whether with the Wrapper or not.

I learned this from here: https://deniapps.com/blog/clarify-react-ref-by-examples Passing ref via custom props is much simpler. The code likes this:

const Parent = props => {
  const divElement = useRef()
  // do something with divElement
  return someCondition ? <Wrapper {...some props} forwardedRef={divElement} /> : <Child forwardedRef={divElement} {...some props} />
}

const Wrapper = props => {
  //MAKE SURE "different props" includes the custom props: forwardedRef from props
  return <Child {...different props} />
}

const Child =({forwardRef, ...rest}) => {
  return <div ref={forwardedRef} {...rest}><some stuff here></div>
}

Upvotes: 2

Reductio
Reductio

Reputation: 539

You shouldn't pass anything from child to parent. Of course you can use callbacks, but you wouldn't use them to pass refs or something similar.

You just should make the Wrapper also a ForwardRef:

const Wrapper = React.forwardRef((props, ref) => {
    return <Child ref={ref} {...your other props} />
})

Now you can just call:

return someCondition ? <Wrapper ref={divElement} {...some props} /> : <Child ref={divElement} {...some props} />

and your ref will always be the div you want.

Upvotes: 0

Related Questions