Wiederverwendung der React-Komponentenlogik mit Render Props

Wenn Sie React für einige Zeit verwendet haben, ist die Wiederverwendung von Komponenten eines der Dinge, die Sie immer tun würden. Der offensichtlichste Weg, den die meisten von uns tun, ist die Verwendung von Komponenten höherer Ordnung.

Durchgelesen Chinonso Johnson‘s Artikel über die Wiederverwendung von React-Komponentenlogik mit HOC. Ich dachte darüber nach, das gleiche Ergebnis zu erzielen, aber stattdessen Render-Requisiten zu verwenden. Dies werden wir in diesem Beitrag behandeln.

Wiederverwendung der Reaktionskomponentenlogik mit Komponenten höherer Ordnung
_Eine Komponente höherer Ordnung ist ein großartiges Muster, das sich als sehr wertvoll erwiesen hat. React betont Komposition gegenüber …_medium.com

Requisiten rendern

Entsprechend Michael Jackson, ist eine Render-Prop eine Funktions-Prop, die eine Komponente verwendet, um zu wissen, was zu rendern ist. Übrigens, wenn Sie Michael Jacksons Video über Render-Requisiten noch nicht gesehen haben, tun Sie es bitte.

Stellen Sie sich zunächst einmal vor, wir hätten eine Anmelde- und eine Anmeldekomponente, die beide den onChange-Ereignishandler haben, der den Status ändert

SignIn-Komponente


import React from 'react';

class SignIn extends React.Component {
  state = {
    auth: {
      email: '',
      password: '',
    },
  };

  onChange = ({ target }) => {
    this.setState({
      auth: {
        ...this.state.auth,
        [target.name]: target.value,
      },
    });
  };

  onSubmit = (event) => {
    event.preventDefault();
    // do something here

    console.log(this.state.auth);
  };

  render() {
    const { email, password } = this.state.auth;
    return (
      <form onSubmit={this.onSubmit}>
        <h4> Sign In </h4>
        <input type="email" name="email" onChange={this.onChange} value={email} />
        <label htmlFor="email">Email</label>

        <input type="password" name="password" onChange={this.onChange} value={password} />
        <label htmlFor="password">Password</label>

        <button type="submit">Submit</button>
      </form>
    );
  }
}

export default SignIn;

Anmeldekomponente

import React from 'react';

class Signup extends React.Component {
  state = {
    auth: {
      email: '',
      password: '',
    },
  };

  onChange = ({ target }) => {
    this.setState({
      auth: {
        ...this.state.auth,
        [target.name]: target.value,
      },
    });
  };

  onSubmit = (event) => {
    event.preventDefault();
    // do something here

    console.log(this.state.auth);
  };

  render() {
    const { email, password, name, username } = this.state.auth;
    return (
      <form onSubmit={this.onSubmit}>
        <h4> Sign Up </h4>
        <label htmlFor="email">Name</label>
        <input type="text" name="name" onChange={this.onChange} value={name} />

        <label htmlFor="email">Username</label>
        <input type="text" name="username" onChange={this.onChange} value={username} />

        <label htmlFor="email">Email</label>
        <input type="email" name="email" onChange={this.onChange} value={email} />

        <input type="password" name="password" onChange={this.onChange} value={password} />
        <label htmlFor="password">Password</label>

        <button type="submit">Submit</button>
      </form>
    );
  }
}

export default Signup;

Wie Sie sehen können, wiederholen sich onChange- und onSubmit-Funktionen sowohl in den Signin- als auch in den Signup-Komponenten. Wir wollen dies nicht tun, da es den Zweck von DRY (Don’t Repeat Yourself) zunichte macht.

Lassen Sie uns nun eine wiederverwendbare Komponente erstellen, die verwendet werden kann, um diese Logik sowohl mit der Signin- als auch mit der Signup-Komponente zu teilen.

Auth-Rendering


import React, { Component } from 'react';

class authRender extends Component {
  state = { auth: {} };

  onChange = ({ target }) => {
    this.setState({
      auth: {
        ...this.state.auth,
        [target.name]: target.value,
      },
    });
  };

  onSubmit = (e) => {
    e.preventDefault();

    console.log(this.state.auth);
  };
  getStateAndHelpers = () => {
    return {
      onChange: this.onChange,
      onSubmit: this.onSubmit,
      auth: this.state.auth,
    };
  };

  render() {
    return this.props.children(this.getStateAndHelpers());
  }
}

export default authRender;

Was wir in der renderProps-Datei gemacht haben, ist, dass wir einfach die Logik von Signin- und Signup-Komponenten in eine separate Komponente übernommen haben, die einfach die untergeordneten Elemente rendert. Sie können dann alle Requisiten übergeben, die innerhalb der untergeordneten Funktion verfügbar sein sollen, obwohl ich mich entschieden habe, sie in eine eigene Funktion zu unterteilen. Dieses Vorgehen wird von empfohlen Kent C. Dodds

Wie verwenden wir es

Es wird dringend empfohlen, Ihre Komponenten in Container und Präsentationskomponenten zu unterteilen. Grundsätzlich haben Container entweder einen Komponentenzustand oder eine Zustandsverwaltung wie Redux.

Wir werden eine neue Datei innerhalb des Containers erstellen, in der der gesamte Zustand und die Ereignishandler enthalten sind.

Anmeldecontainer


import React, { Component } from 'react';
import AuthRender from './renderProps';
import Signin from './Signin';

class signinContainer extends Component {
  render() {
    return (
      <div>
       <Auth>{({ onChange, onSubmit }) => <Signin onChange={onChange} onSubmit={onSubmit} />}</Auth>
      </div>
    );
  }
}

Überarbeitete Anmeldekomponente


import React from 'react';

const SignIn = ({ onChange, onSubmit }) => (
  <form onSubmit={onSubmit}>
    <h4> Sign In </h4>
    		<label htmlFor="email">Email</label>
    <input type="email" name="email" onChange={onChange} className="validate" />
    		<label htmlFor="password">Password</label>
    <input type="password" name="password" onChange={onChange} className="validate" />
    <button type="submit">Submit</button>
  </form>
);

export default SignIn;

Wie wir sehen können, wurde unsere Signin-Komponente in funktionale Komponenten umgestaltet, was das Testen erleichtert. Natürlich ist dies nicht der beste Anwendungsfall für die Verwendung von Render-Requisiten, da es andere einfachere Möglichkeiten gibt, dasselbe ohne HOC oder Render-Requisiten zu erreichen.

Vorteile der Verwendung von Render Props

Wir müssen uns nicht fragen, woher unser Zustand oder unsere Requisiten kommen. Wir können sie in der Argumentliste der Render-Prop sehen.

Es gibt kein automatisches Zusammenführen von Eigenschaftsnamen, daher besteht keine Chance für eine Namenskollision. Michael Jackson

Dies ist richtig, denn wenn Sie sich vorstellen, mehrere HOC auf einer Komponente zu haben, könnten Sie verloren gehen, was es schwierig macht zu wissen, woher die Requisiten kommen.

Fazit

Render Requisiten sind erstaunlich, es kann alles H0C mit einer regulären Komponente machen. Ich ermutige Sie, zuzusehen Michaels Vortrag um es besser zu verstehen und hoffen, dass Sie einen Großteil Ihres HOC umgestalten, um reguläre Komponenten mit Render-Requisiten zu verwenden.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *