Если у меня есть что-то вроде
<Parent>
<Child1 />
<Child2 />
<Child3 />
</Parent>
И я хочу получить доступ из Child2
, где у меня есть refs="child2refs"
, как я могу это сделать?
Если у меня есть что-то вроде
<Parent>
<Child1 />
<Child2 />
<Child3 />
</Parent>
И я хочу получить доступ из Child2
, где у меня есть refs="child2refs"
, как я могу это сделать?
Сначала получите доступ к дочерним элементам: this.props.children
, каждый из них будет иметь свой ref
как свойство на нем.
Если этого нельзя избежать, предложенный шаблон, извлеченный из документов 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
собственности.
Переадресация ссылок является опциональной функцией, которая позволяет некоторым компонентам принимать ссылки, которые они получают, и передавать их дальше (другими словами, "пересылать") дочернему элементу.
Мы создаем Компоненты, которые пересылают свои 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} />;
}
}
Созданные компоненты пересылают свои 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.
/*
* 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
С помощью пересылки ссылок вы можете передать ссылку от родителя к ребенку.
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>;
Примечание. Второй аргумент ref существует только тогда, когда вы определяете компонент с помощью вызова React.forwardRef. Обычные функциональные компоненты или компоненты класса не получают аргумента ref, и ref также недоступен в props.
Пересылка ссылок не ограничивается компонентами DOM. Вы также можете пересылать ссылки на экземпляры компонентов класса.
Ссылка: Реактивная документация.
Я думаю, что это руководство объясняет это довольно хорошо 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>
)
}
}
Вот пример, который сосредоточится на вводе с использованием ссылок (протестировано в 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')
);