Getting DOM node from React child element

Reactjs

Reactjs Problem Overview


Using the React.findDOMNode method that was introduced in v0.13.0 I am able to get the DOM node of each child component that was passed into a parent by mapping over this.props.children.

However, if some of the children happen to be React Elements rather than Components (e.g. one of the children is a <div> created via JSX) React throws an invariant violation error.

Is there a way to get the correct DOM node of each child after mount regardless of what class the child is?

Reactjs Solutions


Solution 1 - Reactjs

this.props.children should either be a ReactElement or an array of ReactElement, but not components.

To get the DOM nodes of the children elements, you need to clone them and assign them a new ref.

render() {
  return (
    <div>
      {React.Children.map(this.props.children, (element, idx) => {
        return React.cloneElement(element, { ref: idx });
      })}
    </div>
  );
}

You can then access the child components via this.refs[childIdx], and retrieve their DOM nodes via ReactDOM.findDOMNode(this.refs[childIdx]).

Solution 2 - Reactjs

If you want to access any DOM element simply add ref attribute and you can directly access that element.

<input type="text" ref="myinput">

And then you can directly:

componentDidMount: function() 
{
	this.refs.myinput.select();
	
},

Their is no need of using ReactDOM.findDOMNode(), if you have added a ref to any element.

Solution 3 - Reactjs

This may be possible by using the refs attribute.

In the example of wanting to to reach a <div> what you would want to do is use is <div ref="myExample">. Then you would be able to get that DOM node by using React.findDOMNode(this.refs.myExample).

From there getting the correct DOM node of each child may be as simple as mapping over this.refs.myExample.children(I haven't tested that yet) but you'll at least be able to grab any specific mounted child node by using the ref attribute.

Here's the official react documentation on refs for more info.

Solution 4 - Reactjs

You can do this using the new React ref api.

function ChildComponent({ childRef }) {
  return <div ref={childRef} />;
}

class Parent extends React.Component {
  myRef = React.createRef();

  get doSomethingWithChildRef() {
    console.log(this.myRef); // Will access child DOM node.
  }

  render() {
    return <ChildComponent childRef={this.myRef} />;
  }
}

Solution 5 - Reactjs

React.findDOMNode(this.refs.myExample) mentioned in another answer has been deprectaed.

use ReactDOM.findDOMNode from 'react-dom' instead

import ReactDOM from 'react-dom'
let myExample = ReactDOM.findDOMNode(this.refs.myExample)

Solution 6 - Reactjs

I found an easy way using the new callback refs. You can just pass a callback as a prop to the child component. Like this:

class Container extends React.Component {
  constructor(props) {
    super(props)
    this.setRef = this.setRef.bind(this)
  }

  setRef(node) {
    this.childRef = node
  }

  render() {
    return <Child setRef={ this.setRef }/>
  }
}

const Child = ({ setRef }) => (
    <div ref={ setRef }>
    </div>
)

Here's an example of doing this with a modal:

class Container extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      modalOpen: false
    }
    this.open = this.open.bind(this)
    this.close = this.close.bind(this)
    this.setModal = this.setModal.bind(this)
  }

  open() {
    this.setState({ open: true })
  }

  close(event) {
    if (!this.modal.contains(event.target)) {
      this.setState({ open: false })
    }
  }

  setModal(node) {
    this.modal = node
  }

  render() {
    let { modalOpen } = this.state
    return (
      <div>
        <button onClick={ this.open }>Open</button>
        {
          modalOpen ? <Modal close={ this.close } setModal={ this.setModal }/> : null
        }
      </div>
    )
  }
}

const Modal = ({ close, setModal }) => (
  <div className='modal' onClick={ close }>
    <div className='modal-window' ref={ setModal }>
    </div>
  </div>
)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGraham ConzettView Question on Stackoverflow
Solution 1 - ReactjsAlexandre KirszenbergView Answer on Stackoverflow
Solution 2 - Reactjsadnan kamiliView Answer on Stackoverflow
Solution 3 - ReactjsPavan RavipatiView Answer on Stackoverflow
Solution 4 - ReactjsLaurenView Answer on Stackoverflow
Solution 5 - ReactjsbhaskarcView Answer on Stackoverflow
Solution 6 - ReactjsWylliam JuddView Answer on Stackoverflow