Refs und das DOM

Refs bieten eine Möglichkeit, auf DOM-Knoten oder React-Elemente zuzugreifen, die mit der Rendermethode erstellt wurden.

Im normalen React-Datenfluss stellen Props die einzige Möglichkeit dar, um übergeordnete Komponenten mit ihren untergeordneten Komponenten interagieren zu lassen. Um ein untergeordnetes Element zu verändern, muss es mit neuen Props erneut gerendert werden. Es gibt jedoch einige Fälle, in denen du ein untergeordnetes Element unbedingt außerhalb des typischen Datenflusses ändern musst. Das zu ändernde untergeordnete Element kann eine Instanz einer React-Komponente oder ein DOM-Element sein. In beiden Fällen bietet React einen Ausweg.

Wann man Refs benutzt

Es gibt einige gute Anwendungsfälle für Refs:

  • Verwalten des Fokus, der Textauswahl oder der Medienwiedergabe.
  • Imperative Animationen auslösen.
  • Integration in DOM-Bibliotheken von Drittanbietern.

Vermeide die Verwendung von Refs für alles, was deklarativ durchgeführt werden kann.

Anstatt beispielsweise die Methoden open () und close () in einer Dialog -Komponente verfügbar zu machen, übergebe ihr eineisOpen-Prop.

Verwende Refs nicht zu häufig

Deine erste Intuition könnte sein, Refs zu verwenden, um Dinge in deiner App “geschehen zu lassen”. Wenn dies der Fall ist, nehme dir einen Moment Zeit und überlege genauer, wo sich der Status in der Komponentenhierarchie befinden sollte. Oft wird klar, dass der richtige Ort, um diesen Zustand zu “besitzen”, auf einer höheren Ebene in der Hierarchie liegt. Beispiele hierfür findest du im Handbuch State anheben.

Hinweis

Die folgenden Beispiele wurden aktualisiert, um die in React 16.3 eingeführte API React.createRef() zu verwenden. Wenn du eine frühere Version von React verwendest, empfehlen wir stattdessen die Verwendung von callback Refs.

Refs erstellen

Refs werden mit React.createRef() erstellt und über das Attribut ref an React-Elemente angehängt. Refs werden häufig einer Instanzeigenschaft zugewiesen, wenn eine Komponente erstellt wird, sodass auf sie in der gesamten Komponente verwiesen werden kann.

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();  }
  render() {
    return <div ref={this.myRef} />;  }
}

Zugreifen auf Refs

Wenn eine Ref an ein Element in render übergeben wird, wird eine Referenz auf den Knoten unter dem Attribut current der Ref zugänglich.

const node = this.myRef.current;

Der Wert der Ref hängt vom Typ des Knotens ab:

  • Wenn das Attribut ref für ein HTML-Element verwendet wird, erhält das im Konstruktor mit React.createRef() erstellte ref das zugrunde liegende DOM-Element als current-Eigenschaft.
  • Wenn das Attribut ref für eine benutzerdefinierte Klassenkomponente verwendet wird, empfängt das Objekt ref die angehängte Instanz der Komponente als current.
  • Darf das Attribut ref für Funktionskomponenten nicht verwenden, da diese keine Instanzen haben.

Die folgenden Beispiele zeigen die Unterschiede.

Hinzufügen eines Ref zu einem DOM-Element

Dieser Code verwendet ein ref, um einen Verweis auf einen DOM-Knoten zu speichern:

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    // Erstelle ein Ref zum Speichern des textInput-DOM-Elements
    this.textInput = React.createRef();    this.focusTextInput = this.focusTextInput.bind(this);
  }

  focusTextInput() {
    // Fokussiere die Texteingabe explizit mit der Raw-DOM-API
    // inweis: Wir greifen auf "current" zu, um den DOM-Knoten zu erhalten
    this.textInput.current.focus();  }

  render() {
    // Sage, dass wir den <input>-Ref mit dem im Konstruktor
    // erstellten `textInput` verknüpfen möchten
    return (
      <div>
        <input
          type="text"
          ref={this.textInput} />        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}

React weist dem DOM-Element die Eigenschaft current zu, wenn die Komponente bereitgestellt wird, und weist sie beim Aufheben der Bereitstellung wieder null zu. ref-Aktualisierungen erfolgen vor componentDidMount- oder componentDidUpdate-Lebenszyklusmethoden.

Hinzufügen eines Ref zu einer Klassenkomponente

Wenn wir den oben genannten CustomTextInput umbrechen wollten, um zu simulieren, dass er unmittelbar nach dem Mounten angeklickt wird, könnten wir einen ref verwenden, um auf die benutzerdefinierte Eingabe zuzugreifen und die MethodefocusTextInput manuell aufzurufen:

class AutoFocusTextInput extends React.Component {
  constructor(props) {
    super(props);
    this.textInput = React.createRef();  }

  componentDidMount() {
    this.textInput.current.focusTextInput();  }

  render() {
    return (
      <CustomTextInput ref={this.textInput} />    );
  }
}

Beachte, dass dies nur funktioniert, wenn CustomTextInput als Klasse deklariert ist:

class CustomTextInput extends React.Component {  // ...
}

Refs und Funktionskomponenten

Darf das Attribut ref nicht für Funktionskomponenten verwenden, da diese keine Instanzen haben:

function MyFunctionComponent() {  return <input />;
}

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.textInput = React.createRef();  }
  render() {
    // Das wird *nicht* funktionieren!
    return (
      <MyFunctionComponent ref={this.textInput} />    );
  }
}

Wenn du zulassen möchtest, dass Benutzer eine Referenz zu deiner Funktionskomponente hinzufügen, kannst du forwardRef verwenden (möglicherweise in Verbindung mit useImperativeHandle), oder du kannst die Komponente in eine Klasse konvertieren.

Du kannst jedoch das Attribut ref in einer Funktionskomponente verwenden, solange du auf ein DOM-Element oder eine Klassenkomponente verweist:

function CustomTextInput(props) {
  // Hier muss textInput deklariert werden, damit die Referenz (ref) darauf verweisen kann  const textInput = useRef(null);
  function handleClick() {
    textInput.current.focus();  }

  return (
    <div>
      <input
        type="text"
        ref={textInput} />      <input
        type="button"
        value="Focus the text input"
        onClick={handleClick}
      />
    </div>
  );
}

Offenlegen von DOM-Refs für übergeordnete Komponenten

In seltenen Fällen möchtest du möglicherweise von einer übergeordneten Komponente aus auf den DOM-Knoten eines untergeordneten Elements zugreifen können. Dies wird im Allgemeinen nicht empfohlen, da es die Verkapselung von Komponenten unterbricht. Es kann jedoch gelegentlich nützlich sein, um den Fokus auszulösen oder die Größe oder Position eines untergeordneten DOM-Knotens zu messen.

Du könntest zwar Hinzufügen eines Ref zu einer Klassenkomponente, dies ist jedoch keine ideale Lösung, da du nur eine Komponenteninstanz anstelle eines DOM-Knotens erhalten würdest. Darüber hinaus würde dies nicht mit Funktionskomponenten funktionieren.

Wenn du React 16.3 oder höher verwendest, empfehlen wir in diesen Fällen die Verwendung von Weiterleiten von Refs. Mit der Weiterleitung von Refs können Komponenten festlegen, dass der Ref jeder untergeordneten Komponente als ihr eigener angezeigt wird. Ein detailliertes Beispiel, wie der DOM-Knoten eine untergeordnete Komponente für eine übergeordnete Komponente verfügbar gemacht wird, findest du in der Dokumentation zur Weiterleiten von Refs.

Wenn du React 16.2 oder eine niedrigere Version verwendest oder mehr Flexibilität benötigst, als durch die Weiterleiten von Refs bereitgestellt wird, kannst du diesen alternativen Ansatz verwenden und einen Ref explizit als übergeben anders benanntes Prop.

Wenn möglich, raten wir davon ab, DOM-Knoten freizulegen, dies kann jedoch ein nützlicher Ausweg sein. Beachte, dass du bei diesem Ansatz der untergeordneten Komponente Code hinzufügen musst. Wenn du absolut keine Kontrolle über die Implementierung der untergeordneten Komponente hast, kannst du als letzte Option findDOMNode () verwenden, dies wird jedoch in StrictMode nicht empfohlen und ist veraltet.

Callback Refs

React unterstützt auch eine andere Methode zum Festlegen von Refs mit der Bezeichnung “Callback Refs”, mit der du genauer steuern kannst, wann Refs festgelegt und deaktiviert werden.

Anstatt ein von createRef() erzeugtes ref-Attribut zu übergeben, übergebe eine Funktion. Die Funktion erhält als Argument die Instanz der React-Komponente oder das HTML-DOM-Element, auf das an anderer Stelle zugegriffen werden kann.

Das folgende Beispiel implementiert ein allgemeines Muster: Speichern eines Verweises auf einen DOM-Knoten in einer Instanzeigenschaft mit dem Rückruf ref.

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);

    this.textInput = null;
    this.setTextInputRef = element => {      this.textInput = element;    };
    this.focusTextInput = () => {      // Fokussiere die Texteingabe mithilfe der DOM-API      if (this.textInput) this.textInput.focus();    };  }

  componentDidMount() {
    // Autofokussiere den Eingang auf Mount
    this.focusTextInput();  }

  render() {
    // Verwenden Sie den `ref` Callback, um einen Verweis auf das
    // Texteingabe-DOM-Element in einem Instanzfeld (z. B. this.textInput)
    // zu speichern.
    return (
      <div>
        <input
          type="text"          ref={this.setTextInputRef}
        />
        <input
          type="button"
          value="Focus the text input"          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}

React ruft den Rückruf ref mit dem DOM-Element auf, wenn die Komponente bereitgestellt wird, und ruft ihn mit null auf, wenn die Bereitstellung aufgehoben wird. Refs sind garantiert auf dem neuesten Stand, bevor componentDidMount oder componentDidUpdate ausgelöst werden.

Du kannst callback Refs zwischen Komponenten übergeben, wie du es mit Objektreferenzen kannst, die mit React.createRef() erstellt wurden.

function CustomTextInput(props) {
  return (
    <div>
      <input ref={props.inputRef} />    </div>
  );
}

class Parent extends React.Component {
  render() {
    return (
      <CustomTextInput
        inputRef={el => this.inputElement = el}      />
    );
  }
}

Im obigen Beispiel übergibt Parent seinen ref Callback als inputRef-Prop an CustomTextInput, undCustomTextInput übergibt die gleiche Funktion wie ein spezielles ref-Attribut an <input>. Infolgedessen wird this.inputElement in Parent auf den DOM-Knoten gesetzt, der dem <input>-Element in CustomTextInput entspricht.

Legacy-API: String Refs

Wenn du zuvor mit React gearbeitet hast, kennst du möglicherweise eine ältere API, bei der das Attribut ref eine String wie "textInput" ist und auf den DOM-Knoten als this.refs.textInput zugegriffen wird. Wir raten davon ab, da String-Refs einige Probleme haben, als Legacy betrachtet werden und wahrscheinlich in einem der entfernt werden zukünftige Versionen.

Hinweis

Wenn du derzeit this.refs.textInput für den Zugriff auf Refs verwendest, empfehlen wir, stattdessen entweder das Callback Muster oder die createRef API zu verwenden.

Caveats mit callback refs

Wenn der ref-Callback als Inline-Funktion definiert ist, wird er bei Aktualisierungen zweimal aufgerufen, zuerst mit null und dann erneut mit dem DOM-Element. Dies liegt daran, dass mit jedem Rendern eine neue Instanz der Funktion erstellt wird. React muss daher die alte Referenz löschen und die neue einrichten. Du kannst dies vermeiden, indem du den ref-Callback als gebundene Methode für die Klasse definierst. Beachte jedoch, dass dies in den meisten Fällen keine Rolle spielen sollte.

Is this page useful?Bearbeite diese Seite