Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

findDOMNode for function components #105

Closed
thysultan opened this issue Feb 16, 2019 · 11 comments
Closed

findDOMNode for function components #105

thysultan opened this issue Feb 16, 2019 · 11 comments

Comments

@thysultan
Copy link

A ReactDOM.findDOMNode equivalent API for function components.

Any container component that doesn't render it's own view would benefit from this addition, for example:

function Foo (props) {
	useLayout(() => React.Children.node(node => element.focus()))

	return props.children
}
@TrySound
Copy link
Contributor

Hey @thysultan There is a good pattern which allows to reuse refs and void merging logic.

const elementRef = React.useRef(null);

return (
  <Popup contentRef={elementRef}>
    <div ref={elementRef}>
    </div>
  </Popup>
)

There is also another proposal which allows to keep refs inside the component. But it's still RFC without implementation. #97

@thysultan
Copy link
Author

thysultan commented Feb 16, 2019

Yes, this is an alternative API to the one mentioned in #97. I'm not sure i understand your example though.

The mentioned use case is when the component in question is not responsible for what it renders thus just returns props.children so you wouldn't be able to attach a ref in that sense.

@TrySound
Copy link
Contributor

My example allows parent component pass ref to your component. It's just a bit more work for consumer.

@silverwind
Copy link

I too am looking for a way to obtain a ref to the top-level child on a component that only renders its children. With class-based components one can do

class Component extends React.Component {
  componentDidMount() {
    const root = ReactDOM.findDOMNode(this);
    // `root` now refers to the top-level child and we can do a side-effect on it
  }

  render() {
    return this.props.children;
  }
}

Any way to do the same on a functional component without rendering useless wrappers?

@j-f1
Copy link

j-f1 commented Jul 17, 2019

You could use React.forwardRef on the component that just renders its children, passing the ref on to the rendered child.

@silverwind
Copy link

passing the ref on to the rendered child.

It could work via adding a forwardRef on the child, but my goal is to not modify the child in any way. Take this example, where I try to use a render prop to obtain the child ref, but it fails because functional component's can't be given refs without forwardRef. It does work when one changes <Child to a regular DOM element like <span but that's also not really what I want to rely on.

Ultimately, I don't think it's possible to replicate the above findDOMNode approach to obtain the child ref in a functional component.

@silverwind
Copy link

silverwind commented Jul 20, 2019

One solution could be to support a ref property on <Fragment>:

function Component({children}) {
  const ref = useRef(null);

  useEffect(() => {
    // `ref.current` now refers to the first non-empty child
  })

  return (
    <Fragment ref={ref}>
      {children}
    </Fragment>
  )
}

The behaviour of ref on a fragment should be copied from findDOMNode:

a component may return a fragment with multiple children, in which case findDOMNode will return the DOM node corresponding to the first non-empty child

@j-f1
Copy link

j-f1 commented Jul 21, 2019

See #97

@silverwind
Copy link

Yep exactly what I had in mind. Maybe close this issue in favor of #97?

@gaearon
Copy link
Member

gaearon commented Aug 24, 2021

Hi, thanks for your suggestion. RFCs should be submitted as pull requests, not issues. I will close this issue but feel free to resubmit in the PR format.

@gaearon gaearon closed this as completed Aug 24, 2021
@Runcode-China
Copy link

I have a idea:
function Component({children}) { const ref = useRef(null); return React.cloneElement(children, { ref: useRef }); }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants