React - How to pass `ref` from child to parent component?
Asked Answered
L

5

26

I have a parent and a child component, I want to access the ref of an element which is in the child component, in my parent component. Can I pass it with props?

// Child Component (Dumb):
export default props =>
    <input type='number' ref='element' />

// Parent Component (Smart):
class Parent extends Component {
    constructor(props) {
        super(props);
    }

    componentDidMount() {
        const node = this.refs.element; // undefined
    }

    render() {
        return <Dumb { ...this.props }/>
    }
}
Lector answered 23/3, 2017 at 15:26 Comment(1)
P
44

You could use the callback syntax for refs:

// Dumb:
export default props =>
    <input type='number' ref={props.setRef} />

// Smart:
class Parent extends Component {
    constructor(props) {
        super(props);
    }

    setRef(ref) {
        this.inputRef = ref;
    }

    render(){
        return <Dumb {...this.props} setRef={this.setRef} />
    }
}
Preclinical answered 23/3, 2017 at 15:33 Comment(5)
I would prefer to use callback instead of passing ref to children component, because you are holding the reference to the parent component. For the simple component works fine but for the large / complicated component as per best practice you should be using callback .V2
@Timo Is there also a way to reference ref in the Dumb component too?Bascio
@timo use ref into the Dumb component, this only works dom elements, Dumb components has not intances thats why he send the DOM into Dumb to the parent.Wadai
How can I give an onChange() to <input> inside <Dumb> compnent and get the ref inside the onChange function definition at parent component?Homogeneous
@Preclinical callback syntax link is deadAutonomic
T
13

With react^16.0.0 you would use React.createRef(). Using @Timo's answer, it would look like this:

// Dumb:
export default props =>
    <input type='number' ref={props.setRef} />

// Smart:
class Parent extends Component {
    constructor(props) {
        super(props);
        this.ref1 = React.createRef()
    }

    render(){
        return <Dumb {...this.props} setRef={this.ref1} />
    }
}
Tallith answered 7/12, 2018 at 18:5 Comment(0)
T
3

As per DOC:

You may not use the ref attribute on functional components because they don't have instances. You should convert the component to a class if you need a ref to it, just like you do when you need lifecycle methods or state.

So i think, if you want to use the ref, you need to use class.

Check this: https://github.com/facebook/react/issues/4936

Tiber answered 23/3, 2017 at 15:51 Comment(1)
This is no longer the case thanks to react hooks, specifically the useRef hook.Brenan
O
3

If you need dynamic refs, because you have an array or something, like I did. Here is what I came up with after reading the answers above.

Also this assumes the myList is an array of objects with a key property. Anyways you get it.

Also this solution works without any issues from TypeScript as well.

const Child = props => <input ref={refElem => setRef(props.someKey, refElem)} />

class Parent extends Component {

    setRef = (key, ref) => {
      this[key] = ref; // Once this function fires, I know about my child :)
    };

    render(){
        return (
          {myList.map(listItem => <Child someKey={listItem.key} setRef={this.setRef} />)}
        )
    }
}

Anyways hope this helps someone.

Overtrade answered 13/2, 2019 at 1:50 Comment(1)
I have the similar problem, but how it will be done using useRef() in react v17??Samarskite
S
1
const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;

Link

https://legacy.reactjs.org/docs/forwarding-refs.html

Solarize answered 5/5, 2023 at 10:10 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.