Demonstration von wiederverwendbaren React-Komponenten in einem Formular

Avatar of Kingsley Silas
Kingsley Silas am

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

Komponenten sind die Bausteine von React-Anwendungen. Es ist fast unmöglich, eine React-Anwendung zu erstellen und keine Komponenten zu verwenden. Es ist so verbreitet, dass einige Drittanbieterpakete Ihnen Komponenten zur Verfügung stellen, die Sie zur Integration von Funktionalitäten in Ihre Anwendung verwenden können.

Diese Komponenten von Drittanbietern sind in der Regel wiederverwendbar. Der Unterschied zwischen ihnen und Komponenten, die Sie wahrscheinlich in Ihrer Anwendung haben, liegt in der Spezifität.

Hier ist, was ich meine. Nehmen wir an, Sie führen ein Unternehmen, das Poloshirts verkauft. Sie können zwei Dinge tun:

  1. Sie können Polos herstellen, die bereits ein Design haben, oder
  2. Sie können den Käufer das gewünschte Design auswählen lassen.

Einige grundlegende Dinge werden konstant sein, wie z. B. dass alle Polos kurzärmelig sein sollten. Aber der Benutzer kann Variationen der Hemden auswählen, wie Farbe und Größe. Ein kurzärmeliges Polo wäre in diesem Fall eine gute React-Komponente: Es ist dasselbe Produkt mit verschiedenen Variationen.

Nehmen wir nun an, Sie arbeiten an einem Anmeldeformular. Wie Poloshirts hat das Formular konsistente Merkmale, aber anstelle von Größen- und Farbvariationen würden wir Eingabefelder, eine Absendetaste und vielleicht sogar einen Link zum Zurücksetzen des Passworts betrachten. Dies kann komponentisiert und mit Variationen bei den Eingaben, Schaltflächen, Links usw. implementiert werden.

Beispiel für ein Eingabeelement

Betrachten wir dies aus der Perspektive der Erstellung eines Eingabefeldes für Ihr Formular. Hier ist, wie eine typische Texteingabe als React-Komponente aussehen würde:

class Form extends React.Component {
  this.state = {
    username: ''
  }
  
  handleChange = (event) => {
    this.setSate({ username: event.target.value })
  }

  render() {
    return (
      <input
        name="username"
        type={type}
        placeholder="Enter username"
        onChange={this.handleChange}
        value={this.state.username}
      />
    )
  }
}

Um dieses Eingabeelement an anderen Stellen und in anderen Projekten wiederverwenden zu können, müssen wir es in eine eigene Komponente extrahieren. Nennen wir sie FormInput.

const FormInput = ({
  name,
  type,
  placeholder,
  onChange,
  className,
  value,
  error,
  children,
  label,
  ...props
}) => {
  
  return (
    <React.Fragment>
      <label htmlFor={name}>{label}</label>
      <input
        id={name}
        name={name}
        type={type}
        placeholder={placeholder}
        onChange={onChange}
        value={value}
        className={className}
        style={error && {border: 'solid 1px red'}}
      />
      { error && <p>{ error }</p>}
    </React.Fragment>
  )
}

FormInput.defaultProps = {
  type: "text",
  className: ""
}

FormInput.propTypes = {
  name: PropTypes.string.isRequired,
  type: PropTypes.string,
  placeholder: PropTypes.string.isRequired,
  type: PropTypes.oneOf(['text', 'number', 'password']),
  className: PropTypes.string,
  value: PropTypes.any,
  onChange: PropTypes.func.isRequired
}

Die Komponente akzeptiert bestimmte Props, wie z. B. die Attribute, die wir benötigen, um die Eingabe mit gültigem Markup zu erstellen, einschließlich des Platzhalters, des Werts und des Namens. Wir richten das Eingabeelement in der Renderfunktion ein und setzen die Attributwerte als die an die Komponente übergebenen Props. Wir binden die Eingabe sogar an ein Label, um sicherzustellen, dass sie immer zusammengehören. Sie können sehen, dass wir keine Annahmen treffen, indem wir etwas vordefinieren. Die Idee ist, sicherzustellen, dass die Komponente in möglichst vielen Szenarien verwendet werden kann.

Dies ist eine gute Komponente, da sie gutes Markup erzwingt (etwas, das Brad Frost als dumb React bezeichnet) und zeigt, dass nicht jede Komponente eine hochkomplexe Funktionalität sein muss. Andererseits, wenn wir über etwas sehr Einfaches sprechen würden, sagen wir eine statische Überschrift, dann könnte die Verwendung einer React-Komponente übertrieben sein. Der mögliche Maßstab für die Erstellung einer wiederverwendbaren Komponente wäre wahrscheinlich, wenn Sie dieselbe Funktionalität an anderen Stellen einer Anwendung benötigen. Es gibt *im Allgemeinen* keinen Bedarf für eine "wiederverwendbare" Komponente, wenn diese Komponente nur einmal verwendet wird.

Wir können unsere Eingabekomponente in einer anderen Komponente, der LoginPage, verwenden.

class LoginPage extends React.Component {
  state = {
    user: {
      username: "",
      password: ""
    },
    errors: {},
    submitted: false
  };

  handleChange = event => {
    const { user } = this.state;
    user[event.target.name] = event.target.value;
    this.setState({ user });
  };

  onSubmit = () => {
    const {
      user: { username, password }
    } = this.state;
    let err = {};

    if (!username) {
      err.username = "Enter your username!";
    }

    if (password.length < 8) {
      err.password = "Password must be at least 8 characters!";
    }

    this.setState({ errors: err }, () => {
      if (Object.getOwnPropertyNames(this.state.errors).length === 0) {
        this.setState({ submitted: true });
      }
    });
  };

  render() {
    const {
      submitted,
      errors,
      user: { username, password }
    } = this.state;
    return (
      <React.Fragment>
        {submitted ? (
          <p>Welcome onboard, {username}!</p>
        ) : (
          <React.Fragment>
            <h3>Login!</h3>
            <FormInput
              label="Username"
              name="username"
              type="text"
              value={username}
              onChange={this.handleChange}
              placeholder="Enter username..."
              error={errors.username}
              required
              className="input"
            />

            <FormInput
              label="Password"
              name="password"
              type="password"
              value={password}
              onChange={this.handleChange}
              placeholder="Enter password..."
              error={errors.password}
              className="input"
              required
            />

            <Button
              type="submit"
              label="Submit"
              className="button"
              handleClick={this.onSubmit}
            />
          </React.Fragment>
        )}
      </React.Fragment>
    );
  }
}

Sehen Sie, wie LoginPage die FormInput zweimal verwendet? Wir verwenden sie sowohl als Texteingabe für einen Benutzernamen als auch als weitere Texteingabe für ein Passwort. Wenn wir Änderungen daran vornehmen möchten, wie die Eingabe funktioniert, können wir diese Änderungen in der FormInput-Komponentendatei vornehmen, die wir erstellt haben, und sie werden auf jede Instanz angewendet, in der die Eingabekomponente verwendet wird. Das ist der grundlegende Vorteil von wiederverwendbaren Komponenten: Sie müssen sich nicht wiederholen.

Selbst die Fehler werden von der FormInput-Komponente angezeigt.

Die Funktion onSubmit validiert zuerst das user-Objekt, das wir aus dem Formular erhalten, und stellt sicher, dass es der Struktur entspricht, d. h. dass ein Wert für username vorhanden ist. Beachten Sie, dass wir die Funktionalität der Eingabe sogar erweitern können, wie wir es getan haben, um zu überprüfen, ob das Passwort mindestens acht Zeichen enthält.

Wenn Sie sich den Code ansehen, werden Sie sehen, dass dort eine Button-Komponente vorhanden ist. Das ist nicht dasselbe wie ein HTML-<button>-Element, sondern eine andere Komponente, die die Props entgegennimmt, die den Typ der gewünschten Schaltfläche (submit, reset, button), ihre Klasse, was beim Klicken zu tun ist, und die Beschriftung definieren. Es gibt viele andere Schaltflächenattribute, die wir integrieren könnten, um jeden benötigten Standard durchzusetzen.

const Button = (props) => (
  <button
    type={props.type}
    className={props.className}
    onClick={props.handleClick}
  >
    {props.label}
  </button>
)

Hier ist unser finales Anmeldeformular, wenn all unsere Komponenten zusammengefügt sind.

Siehe den Pen
Wiederverwendbare Button-Komponente
von Kingsley Silas Chijioke (@kinsomicrote)
auf CodePen.


Möchten Sie das selbst ausprobieren? Versuchen Sie, ein wiederverwendbares <select>-Element zu erstellen. Wenn das zu schwierig ist, können Sie mit einem <textarea>-Element beginnen, dann vielleicht mit einer Checkbox, bevor Sie sich mit <select> befassen. Die Kernidee ist, es allgemein zu gestalten. Ich würde gerne sehen, was Sie sich ausgedacht haben, also verlinken Sie Ihre Arbeit im Kommentarbereich!