Реагировать - как передать `ref` от дочернего компонента к родительскому?

У меня есть родительский и дочерний компоненты, я хочу получить доступ к ref элемента, который находится в дочернем компоненте, в моем родительском компоненте. Могу я пройти его с реквизитом?

// 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 }/>
    }
}

person Nick1R1    schedule 23.03.2017    source источник


Ответы (4)


Вы можете использовать синтаксис обратного вызова для ссылок:

// 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} />
    }
}
person TimoStaudinger    schedule 23.03.2017
comment
Я бы предпочел использовать обратный вызов вместо передачи ref дочернему компоненту, потому что вы держите ссылку на родительский компонент. Для простого компонента работает нормально, но для большого / сложного компонента в соответствии с передовой практикой вы должны использовать обратный вызов. - person Khalid Azam; 27.03.2017
comment
@Timo Есть ли способ также ссылаться на ref в компоненте Dumb? - person Anil Namde; 05.07.2018
comment
@timo использует ref в Dumb-компоненте, это работает только с элементами dom, Dumb-компоненты не имеют intances, поэтому он отправляет DOM в Dumb родителю. - person elporfirio; 01.09.2018
comment
Как я могу присвоить onChange() <input> внутри <Dumb> компонента и получить ref внутри определения onChange функции в родительском компоненте? - person Hareesh; 09.05.2019

С response ^ 16.0.0 вы должны использовать React.createRef (). Используя ответ @ Timo, это будет выглядеть так:

// 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} />
    }
}
person bbrinx    schedule 07.12.2018

Согласно DOC:

Вы не можете использовать атрибут ref в функциональных компонентах, потому что у них нет экземпляров. Вы должны преобразовать компонент в класс, если вам нужна ссылка на него, точно так же, как вы это делаете, когда вам нужны методы или состояние жизненного цикла.

Поэтому я думаю, что если вы хотите использовать ref, вам нужно использовать class.

Проверьте это: https://github.com/facebook/react/issues/4936

person Mayank Shukla    schedule 23.03.2017
comment
Это больше не так, благодаря перехватчикам реакции, в частности перехватчику useRef. - person oskar132; 14.05.2019

Если вам нужны динамические ссылки, потому что у вас есть массив или что-то в этом роде, как у меня. Вот что я придумал, прочитав ответы выше.

Также предполагается, что myList - это массив объектов со свойством key. В любом случае вы это получите.

Также это решение работает без каких-либо проблем с TypeScript.

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} />)}
        )
    }
}

В любом случае надеюсь, что это кому-то поможет.

person Thomas Valadez    schedule 13.02.2019
comment
У меня аналогичная проблема, но как это будет сделано с помощью useRef () в react v17 ?? - person Divyank Saxena; 19.05.2021