Как получить доступ к refs дочернего компонента в родительском компоненте

Если у меня есть что-то вроде

<Parent>
  <Child1 />
  <Child2 />
  <Child3 />
</Parent>

И я хочу получить доступ из Child2, где у меня есть refs="child2refs", как я могу это сделать?

Ответ 1

Сначала получите доступ к дочерним элементам: this.props.children, каждый из них будет иметь свой ref как свойство на нем.

Ответ 2

Рекомендуется для версий React до 16.3

Если этого нельзя избежать, предложенный шаблон, извлеченный из документов React, будет:

import React, { Component } from 'react';

const Child = ({ setRef }) => <input type="text" ref={setRef} />;

class Parent extends Component {
    constructor(props) {
        super(props);
        this.setRef = this.setRef.bind(this);
    }

    componentDidMount() {
        // Calling a function on the Child DOM element
        this.childRef.focus();
    }

    setRef(input) {
        this.childRef = input;
    }

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

Родитель передает функцию в качестве опоры, связанную с Родителя this. Когда React призывам ребенок ref проп setRef он назначит ребенок ref к Родителю childRef собственности.

Рекомендуется для реакции> = 16,3

Переадресация ссылок является опциональной функцией, которая позволяет некоторым компонентам принимать ссылки, которые они получают, и передавать их дальше (другими словами, "пересылать") дочернему элементу.

Мы создаем Компоненты, которые пересылают свои ref с React.forwardRef. Возвращаемый компонент Component ref должен иметь тот же тип, что и возвращаемый тип React.createRef. Всякий раз, когда React монтирует узел DOM, current свойство ref созданной с помощью React.createRef будет указывать на базовый узел DOM.

import React from "react";

const LibraryButton = React.forwardRef((props, ref) => (
  <button ref={ref} {...props}>
    FancyButton
  </button>
));

class AutoFocus extends React.Component {
  constructor(props) {
    super(props);
    this.childRef = React.createRef();
    this.onClick = this.onClick.bind(this);
  }

  componentDidMount() {
    this.childRef.current.focus();
  }

  onClick() {
    console.log("fancy!");
  }

  render() {
    return <LibraryButton onClick={this.onClick} ref={this.childRef} />;
  }
}

Пример пересылки ссылок HOC

Созданные компоненты пересылают свои ref на дочерний узел.

function logProps(Component) {
  class LogProps extends React.Component {
    componentDidUpdate(prevProps) {
      console.log('old props:', prevProps);
      console.log('new props:', this.props);
    }

    render() {
      const {forwardedRef, ...rest} = this.props;

      // Assign the custom prop "forwardedRef" as a ref
      return <Component ref={forwardedRef} {...rest} />;
    }
  }

  // Note the second param "ref" provided by React.forwardRef.
  // We can pass it along to LogProps as a regular prop, e.g. "forwardedRef"
  // And it can then be attached to the Component.
  return React.forwardRef((props, ref) => {
    return <LogProps {...props} forwardedRef={ref} />;
  });
}

См. Пересылка ссылок в документах React.

Ответ 3

  1. Внутри дочернего компонента добавьте ссылку на нужный вам узел
  2. Внутри родительского компонента добавьте ссылку на дочерний компонент.
/*
* Child component
*/
class Child extends React.Component {
  render() {
    return (
      <div id="child">
        <h1 ref={(node) => { this.heading = node; }}>
          Child
        </h1>
      </div>
    );
  }
}

/*
 * Parent component
 */
class Parent extends React.Component {
  componentDidMount() {
    // Access child component refs via parent component instance like this
    console.log(this.child.heading.getDOMNode());
  }

  render() {
    return (
      <div>
        <Child
          ref={(node) => { this.child = node; }}
        />
      </div>
    );
  }
}

Демонстрация: https://codepen.io/itsfadnis/pen/aLWVVx?editors=0011

Ответ 4

С помощью пересылки ссылок вы можете передать ссылку от родителя к ребенку.

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>;
  1. Создайте ссылку React, вызвав React.createRef, и присвойте ее переменной ref.
  2. Передайте ваш ref, указав его как атрибут JSX.
  3. React передает ref в функцию (props, ref) =>... внутри forwardRef в качестве второго аргумента.
  4. Перешлите этот аргумент ref, указав его в качестве атрибута JSX.
  5. Когда ссылка прикреплена, ref.current будет указывать на узел DOM.

Примечание. Второй аргумент ref существует только тогда, когда вы определяете компонент с помощью вызова React.forwardRef. Обычные функциональные компоненты или компоненты класса не получают аргумента ref, и ref также недоступен в props.

Пересылка ссылок не ограничивается компонентами DOM. Вы также можете пересылать ссылки на экземпляры компонентов класса.

Ссылка: Реактивная документация.

Ответ 5

Я думаю, что это руководство объясняет это довольно хорошо https://github.com/yannickcr/eslint-plugin-react/issues/678

class Field extends Component {
  const { inputRef } = this.props;
  render() {
    return (
      <input type="text" ref={inputRef} />
    )
  }
}

class MyComponent extends Component {
  componentDidMount() {
    this.inputNode.focus();
  }

  render() {
    return (
      <div>
        Hello, <Field inputRef={node => this.inputNode = node} />
      </div>
    )
  }
}

Ответ 6

Вот пример, который сосредоточится на вводе с использованием ссылок (протестировано в React 16.8.6):

Дочерний компонент:

class Child extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
  render() {
    return (<input type="text" ref={this.myRef} />);
  }
}

Родительский компонент с дочерним компонентом внутри:

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.childRef = React.createRef();
  }
  componentDidMount() {
    this.childRef.current.myRef.current.focus();
  }
  render() {
    return <Child ref={this.childRef} />;
  }
}

ReactDOM.render(
    <Parent />,
    document.getElementById('container')
);

Родительский компонент с this.props.children:

class Parent extends React.Component {
    constructor(props) {
        super(props);
        this.childRef = React.createRef();
    }
    componentDidMount() {
        this.childRef.current.myRef.current.focus();
    }
    render() {
        const ChildComponentWithRef = React.forwardRef((props, ref) =>
            React.cloneElement(this.props.children, {
                ...props,
                ref
            })
        );
        return <ChildComponentWithRef ref={this.childRef} />
    }
}

ReactDOM.render(
    <Parent>
        <Child />
    </Parent>,
    document.getElementById('container')
);