Arbeiten mit Refs in React

Avatar of Kingsley Silas
Kingsley Silas am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Refs ermöglichen den direkten Zugriff auf DOM-Knoten innerhalb von React. Dies ist in Situationen nützlich, in denen Sie beispielsweise das Kind einer Komponente ändern möchten. Angenommen, Sie möchten den Wert eines <input>-Elements ändern, aber ohne Props zu verwenden oder die gesamte Komponente neu zu rendern.

Das ist die Art von Dingen, für die Refs gut sind und die wir in diesem Beitrag untersuchen werden.

UPDATE: useRef Hook

Dies wurde ursprünglich vor React Hooks geschrieben. Falls Sie danach suchen, hier ist ein kurzes Beispiel

Sehen Sie den Pen
React useRef Hook
von CodePen (@codepen)
auf CodePen.

Der Rest dieses Beitrags befasst sich mit Refs, was in Bezug auf das Was und Warum von Refs immer noch relevant ist.

Wie man eine Ref erstellt

createRef() ist eine neue API, die mit React 16.3 eingeführt wurde. Sie können eine Ref erstellen, indem Sie React.createRef() aufrufen und ihr ein React-Element über das Attribut ref auf dem Element zuweisen.

class Example extends React.Component {
  constructor(props) {
    super(props)

    // Create the ref
    this.exampleRef = React.createRef()
  }

  render() {
    return (
      <div>
        // Call the ref with the `ref` attribute
        <input type="text" ref={this.exampleRef} />
      </div>
    )
  }
}

Wir können mit dem Attribut current der Ref auf den Knoten der im Render-Method erstellten Ref verweisen. Aus dem obigen Beispiel wäre das this.exampleRef.current.

Hier ist ein Beispiel:

Sehen Sie den Pen React Ref – createRef von Kingsley Silas Chijioke (@kinsomicrote) auf CodePen.

class App extends React.Component {
  constructor(props) {
    super(props)
    
    // Create the ref
    this.textInput = React.createRef();
    this.state = {
      value: ''
    }
  }
  
  // Set the state for the ref
  handleSubmit = e => {
    e.preventDefault();
    this.setState({ value: this.textInput.current.value})
  };

  render() {
    return (
      <div>
        <h1>React Ref - createRef</h1>
        // This is what will update
        <h3>Value: {this.state.value}</h3>
        <form onSubmit={this.handleSubmit}>
          // Call the ref on <input> so we can use it to update the <h3> value
          <input type="text" ref={this.textInput} />
          <button>Submit</button>
        </form>
      </div>
    );
  }
}
Wie ein Gespräch zwischen einer Kindkomponente und einem Element, das die Ref enthält, ablaufen könnte.

Dies ist eine Komponente, die Text, ein Eingabefeld und einen Button rendert. Die Ref wird im Konstruktor erstellt und dann dem Eingabeelement zugewiesen, wenn es gerendert wird. Wenn der Button geklickt wird, wird der vom Eingabeelement (das die Ref zugewiesen hat) übermittelte Wert verwendet, um den Status des Texts (in einem H3-Tag) zu aktualisieren. Wir verwenden this.textInput.current.value, um auf den Wert zuzugreifen, und der neue Status wird dann auf dem Bildschirm gerendert.

Eine Callback-Funktion an Ref übergeben

React ermöglicht es Ihnen, eine Ref zu erstellen, indem Sie eine Callback-Funktion an das Attribut ref einer Komponente übergeben. So sieht das aus

<input type="text" ref={element => this.textInput = element} />

Der Callback wird verwendet, um eine Referenz auf den DOM-Knoten in einer Instanz-Eigenschaft zu speichern. Wenn wir diese Referenz nutzen wollen, greifen wir darauf über

this.textInput.value

Sehen wir uns an, wie das im selben Beispiel aussieht, das wir zuvor verwendet haben.

Sehen Sie den Pen React Ref – Callback Ref von Kingsley Silas Chijioke (@kinsomicrote) auf CodePen.

class App extends React.Component {
    state = {
    value: ''
  }
  
  handleSubmit = e => {
    e.preventDefault();
    this.setState({ value: this.textInput.value})
  };

  render() {
    return (
      <div>
        <h1>React Ref - Callback Ref</h1>
        <h3>Value: {this.state.value}</h3>
        <form onSubmit={this.handleSubmit}>
          <input type="text" ref={element => this.textInput = element} />
          <button>Submit</button>
        </form>
      </div>
    );
  }
}

Wenn Sie eine Callback wie oben verwenden, ruft React die Ref-Callback mit dem DOM-Knoten auf, wenn die Komponente gemountet wird. Wenn die Komponente unmounted wird, ruft es sie mit null auf.

Es ist auch möglich, eine Ref von einer übergeordneten Komponente mit Hilfe von Callbacks an eine untergeordnete Komponente weiterzugeben.

Sehen Sie den Pen React Ref – Callback Ref 2 von Kingsley Silas Chijioke (@kinsomicrote) auf CodePen.

Erstellen wir unsere „dumme“ Komponente, die eine einfache Eingabe rendert

const Input = props => {
  return (
    <div>
      <input type="text" ref={props.inputRef} />
    </div>
  );
};

Diese Komponente erwartet die inputRef-Props von ihrer übergeordneten Komponente, die dann verwendet werden, um eine Ref auf den DOM-Knoten zu erstellen.

Hier ist die übergeordnete Komponente

class App extends React.Component {
  state = {
    value: ''
  };

  handleSubmit = event => {
    this.setState({ value: this.inputElement.value });
  };

  render() {
    return (
      <div>
        <h1>React Ref - Callback Ref</h1>
        <h3>Value: {this.state.value}</h3>
        <Input inputRef={el => (this.inputElement = el)} />
        <button onClick={this.handleSubmit}>Submit</button>
      </div>
    );
  }
}

In der App-Komponente wollen wir den Text erhalten, der in das Eingabefeld (das sich in der Kindkomponente befindet) eingegeben wird, damit wir ihn rendern können. Die Ref wird mit einem Callback erstellt, wie wir es im ersten Beispiel dieses Abschnitts getan haben. Der Schlüssel liegt darin, wie wir von der App-Komponente auf das DOM des Eingabeelements in der Eingabekomponente zugreifen. Wenn Sie genau hinschauen, greifen wir darauf über this.inputElement zu. Wenn wir also den Status des Werts in der App-Komponente aktualisieren, erhalten wir den Text, der in das Eingabefeld eingegeben wurde, über this.inputElement.value.

Das ref-Attribut als String

Dies ist der alte Weg, eine Ref zu erstellen, und er wird wahrscheinlich in einer zukünftigen Version entfernt werden, da einige Probleme damit verbunden sind. Das React-Team rät davon ab, es zu verwenden und kennzeichnet es sogar als „Legacy“ in der Dokumentation. Wir nehmen es hier trotzdem auf, da es die Möglichkeit gibt, dass Sie es in einer Codebasis antreffen.

Sehen Sie den Pen React Ref – String Ref von Kingsley Silas Chijioke (@kinsomicrote) auf CodePen.

Zurück zu unserem Beispiel eines Eingabefelds, dessen Wert beim Absenden zur Aktualisierung eines Textwerts verwendet wird

class App extends React.Component {
    state = {
    value: ''
  }
  
  handleSubmit = e => {
    e.preventDefault();
    this.setState({ value: this.refs.textInput.value})
  };

  render() {
    return (
      <div>
        <h1>React Ref - String Ref</h1>
        <h3>Value: {this.state.value}</h3>
        <form onSubmit={this.handleSubmit}>
          <input type="text" ref="textInput" />
          <button>Submit</button>
        </form>
      </div>
    );
  }
}

Die Komponente wird initialisiert und wir beginnen mit einem Standard-Statuswert, der auf einen leeren String gesetzt ist (value='’). Die Komponente rendert wie üblich den Text und das Formular, und wie zuvor aktualisiert der H3-Text seinen Status, wenn das Formular mit dem eingegebenen Inhalt übermittelt wird.

Wir haben eine Ref erstellt, indem wir die ref-Eigenschaft des Eingabefelds auf textInput gesetzt haben. Das gibt uns Zugriff auf den Wert der Eingabe in der handleSubmit()-Methode über this.refs.textInput.value.

Weiterleiten einer Ref von einer Komponente zu einer anderen

**Ref-Weiterleitung ist die Technik, eine Ref von einer Komponente an eine untergeordnete Komponente weiterzugeben, indem die Methode React.forwardRef() verwendet wird.

Sehen Sie den Pen React Ref – forward Ref von Kingsley Silas Chijioke (@kinsomicrote) auf CodePen.

Zurück zu unserem laufenden Beispiel eines Eingabefelds, das den Textwert bei Übermittlung aktualisiert

class App extends React.Component {
    constructor(props) {
      super(props)
      this.inputRef = React.createRef();
      this.state = {
        value: ''
      }
    }
  
  handleSubmit = e => {
    e.preventDefault();
    this.setState({ value: this.inputRef.current.value})
  };

  render() {
    return (
      <div>
        <h1>React Ref - createRef</h1>
        <h3>Value: {this.state.value}</h3>
        <form onSubmit={this.handleSubmit}>
          <Input ref={this.inputRef} />
          <button>Submit</button>
        </form>
      </div>
    );
  }
}

Wir haben die Ref in diesem Beispiel mit inputRef erstellt, die wir als ref-Attribut an die Kindkomponente weitergeben wollen, die wir zur Aktualisierung des Status unseres Textes verwenden können.

const Input = React.forwardRef((props, ref) => (
  <input type="text" ref={ref} />
));

Hier ist eine alternative Möglichkeit, dies zu tun, indem die Ref außerhalb der App-Komponente definiert wird

const Input = React.forwardRef((props, ref) => (
  <input type="text" ref={ref} />
));

const inputRef = React.createRef();

class App extends React.Component {
    constructor(props) {
      super(props)
      
      this.state = {
        value: ''
      }
    }
  
  handleSubmit = e => {
    e.preventDefault();
    this.setState({ value: inputRef.current.value})
  };

  render() {
    return (
      <div>
        <h1>React Ref - createRef</h1>
        <h3>Value: {this.state.value}</h3>
        <form onSubmit={this.handleSubmit}>
          <Input ref={inputRef} />
          <button>Submit</button>
        </form>
      </div>
    );
  }
}

Verwendung von Ref für die Formularvalidierung

Wir alle wissen, dass die Formularvalidierung super schwierig ist, aber etwas, wofür React gut geeignet ist. Sie wissen schon, Dinge wie sicherzustellen, dass ein Formular nicht mit einem leeren Eingabewert abgeschickt werden kann. Oder ein Passwort mit mindestens sechs Zeichen zu verlangen. Refs können für diese Arten von Situationen nützlich sein.

Sehen Sie den Pen React ref Pen – validation von Kingsley Silas Chijioke (@kinsomicrote) auf CodePen.

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

    this.username = React.createRef();
    this.password = React.createRef();
    this.state = {
      errors: []
    };
  }

  handleSubmit = (event) => {
    event.preventDefault();
    const username = this.username.current.value;
    const password = this.password.current.value;
    const errors = this.handleValidation(username, password);

    if (errors.length > 0) {
      this.setState({ errors });
      return;
    }
    // Submit data
  };

  handleValidation = (username, password) => {
    const errors = [];
    // Require username to have a value on submit
    if (username.length === 0) {
      errors.push("Username cannot be empty");
    }
    
    // Require at least six characters for the password
    if (password.length < 6) {
      errors.push("Password should be at least 6 characters long");
    }
    
    // If those conditions are met, then return error messaging
    return errors;
  };

  render() {
    const { errors } = this.state;
    return (
      <div>
        <h1>React Ref Example</h1>
        <form onSubmit={this.handleSubmit}>
          // If requirements are not met, then display errors
          {errors.map(error => <p key={error}>{error}</p>)}
          <div>
            <label>Username:</label>
            // Input for username containing the ref
            <input type="text" ref={this.username} />
          </div>
          <div>
            <label>Password:</label>
            // Input for password containing the ref
            <input type="text" ref={this.password} />
          </div>
          <div>
            <button>Submit</button>
          </div>
        </form>
      </div>
    );
  }
}

Wir haben createRef() verwendet, um Refs für die Eingaben zu erstellen, die wir dann als Parameter an die Validierungsmethode übergeben haben. Wir füllen das errors-Array, wenn eine der Eingaben einen Fehler aufweist, den wir dann dem Benutzer anzeigen.

Das ist eine Ref... äh, ein Wrap!

Hoffentlich gibt Ihnen dieser Überblick ein gutes Verständnis dafür, wie leistungsfähig Refs sein können. Sie sind eine hervorragende Möglichkeit, einen Teil einer Komponente zu aktualisieren, ohne die gesamte Komponente neu rendern zu müssen. Das ist praktisch für das Schreiben von schlankeren Codes und für eine bessere Leistung.

Gleichzeitig ist es ratsam, den Rat der React-Dokumentation selbst zu beherzigen und Refs nicht übermäßig zu verwenden

Ihre erste Neigung könnte darin bestehen, Refs zu verwenden, um „Dinge geschehen zu lassen“ in Ihrer App. Wenn dies der Fall ist, nehmen Sie sich einen Moment Zeit und denken Sie kritischer darüber nach, woher der Status in der Komponenten-Hierarchie kommen sollte. Oft wird deutlich, dass die richtige Stelle, um diesen Status zu „besitzen“, auf einer höheren Ebene in der Hierarchie liegt.

Verstanden? Erfasst? Gut.