web-dev-qa-db-ger.com

Wie bearbeite ich mehrere eingabesteuerte Komponenten in React?

Ich habe eine Komponente, die ein Kontaktobjekt als Status speichert - {firstName: "John", lastName: "Doe", phone: "1234567890} Ich möchte ein Formular erstellen, um dieses Objekt zu bearbeiten, aber wenn die Eingaben den Wert enthalten sollen Für den ursprünglichen Kontaktparameter muss ich jeden Eingang zu einer kontrollierten Komponente machen, jedoch weiß ich nicht, wie ich eine handleChange-Funktion erstellen kann, die sich an jeden Parameter anpasst, da mein Status nur {contact: {...}} enthält. Unten ist was ich momentan habe -

  getInitialState: function () {
    return ({contact: {}});
  },
  handleChange: function (event) {
    this.setState({contact: event.target.value });
  },
  render: function () {
    return (
        <div>
          <input type="text" onChange={this.handleChange} value={this.state.contact.firstName}/>
          <input type="text" onChange={this.handleChange} value={this.state.contact.lastName}/>
          <input type="text" onChange={this.handleChange} value={this.state.contact.lastName}/>
        </div>
      );
    }

Ich wünschte, in meinem Griff kann ich so etwas machen

  handleChange: function (event) {
    this.setState({contact.firstName: event.target.value });
  }
25
akantoword

Es gibt einen "einfachen" Weg, dies zu tun, und einen "intelligenten" Weg. Wenn Sie mich fragen, ist es nicht immer der beste Weg, Dinge auf intelligente Weise zu tun, da ich später vielleicht schwieriger damit arbeiten kann. In diesem Fall sind beide durchaus verständlich.

Randbemerkung: Eine Sache, über die ich nachdenken sollte, ist, müssen Sie das contact-Objekt aktualisieren, oder können Sie firstName direkt auf dem Status belassen? Möglicherweise haben Sie viele Daten im Status der Komponente? Wenn dies der Fall ist, ist es wahrscheinlich eine gute Idee, sie in kleinere Komponenten mit engeren Verantwortlichkeiten aufzuteilen.

Der "einfache" Weg

  changeFirstName: function (event) {
    const contact = this.state.contact;
    contact.firstName = event.target.value;
    this.setState({ contact: contact });
  },
  changeLastName: function (event) {
    const contact = this.state.contact;
    contact.lastName = event.target.value;
    this.setState({ contact: contact });
  },
  changePhone: function (event) {
    const contact = this.state.contact;
    contact.phone = event.target.value;
    this.setState({ contact: contact });
  },
  render: function () {
    return (
      <div>
        <input type="text" onChange={this.changeFirstName.bind(this)} value={this.state.contact.firstName}/>
        <input type="text" onChange={this.changeLastName.bind(this)} value={this.state.contact.lastName}/>
        <input type="text" onChange={this.changePhone.bind(this)} value={this.state.contact.phone}/>
      </div>
    );
  }

Der "smarte" Weg

  handleChange: function (propertyName, event) {
    const contact = this.state.contact;
    contact[propertyName] = event.target.value;
    this.setState({ contact: contact });
  },
  render: function () {
    return (
      <div>
        <input type="text" onChange={this.handleChange.bind(this, 'firstName')} value={this.state.contact.firstName}/>
        <input type="text" onChange={this.handleChange.bind(this, 'lastName')} value={this.state.contact.lastName}/>
        <input type="text" onChange={this.handleChange.bind(this, 'phone')} value={this.state.contact.lastName}/>
      </div>
    );
  }



Update: Gleiche Beispiele mit ES2015 +

Dieser Abschnitt enthält die gleichen Beispiele wie oben gezeigt, verwendet jedoch Funktionen von ES2015 +.

Um die folgenden Funktionen über Browser hinweg zu unterstützen, müssen Sie Ihren Code mit Babel mit den Voreinstellungen es2015 und reag , Und dem Plugin transpilieren Stufe 0 .

Nachfolgend finden Sie aktualisierte Beispiele. Verwenden Sie Objektzerstrukturierung , um den Kontakt aus dem Status Spread-Operator in Abzurufen. Erstellen Sie ein aktualisiertes Kontaktobjekt, anstatt das vorhandene zu mutieren Erstellen von Komponenten als Klassen um Erweitern von React.Component , und Verwenden von Pfeil-Funktionen , um Callbacks zu erstellen. t muss bind(this).

Der "einfache" Weg, ES2015 +

class ContactEdit extends React.Component {

  changeFirstName = (event) => {
    const { contact } = this.state;
    const newContact = {
      ...contact,
      firstName: event.target.value
    };
    this.setState({ contact: newContact });
  }
  changeLastName = (event) => {
    const { contact } = this.state;
    const newContact = {
      ...contact,
      lastName: event.target.value
    };
    this.setState({ contact: newContact });
  }
  changePhone = (event) => {
    const { contact } = this.state;
    const newContact = {
      ...contact,
      phone: event.target.value
    };
    this.setState({ contact: newContact });
  }

  render() {
    return (
      <div>
        <input type="text" onChange={this.changeFirstName} value={this.state.contact.firstName}/>
        <input type="text" onChange={this.changeLastName} value={this.state.contact.lastName}/>
        <input type="text" onChange={this.changePhone} value={this.state.contact.phone}/>
      </div>
    );
  }
}

Der "smarte" Weg, ES2015 +

Beachten Sie, dass handleChangeFor eine curried-Funktion : .__ ist. Wenn Sie sie mit einer propertyName aufrufen, wird eine Rückruffunktion erstellt, die beim Aufruf [propertyName] des Kontaktobjekts (New) im Status aktualisiert.

class ContactEdit extends React.Component {

  handleChangeFor = (propertyName) => (event) => {
    const { contact } = this.state;
    const newContact = {
      ...contact,
      [propertyName]: event.target.value
    };
    this.setState({ contact: newContact });
  }

  render() {
    return (
      <div>
        <input type="text" onChange={this.handleChangeFor('firstName')} value={this.state.contact.firstName}/>
        <input type="text" onChange={this.handleChangeFor('lastName')} value={this.state.contact.lastName}/>
        <input type="text" onChange={this.handleChangeFor('phone')} value={this.state.contact.lastName}/>
      </div>
    );
  }
}
55
ArneHugo

ES6 Ein-Liner-Ansatz

<input type="text" 
       value={this.state.username}
       onChange={(e) => this.setState({ username: e.target.value })}
       id="username"/>
8
Stuart P.

Es gibt zwei Möglichkeiten, den Status eines verschachtelten Objekts zu aktualisieren:

  1. Erstellen Sie mit JSON.parse (JSON.stringify (object)) eine Kopie des Objekts, aktualisieren Sie die Kopie und übergeben Sie sie an setState.
  2. Verwenden Sie die immutability-Helfer in den Reakti- ons-Addons . Dies ist der empfohlene Weg.

Wie das funktioniert, erfahren Sie in JS Fiddle . Der Code ist auch unten:

var Component = React.createClass({
    getInitialState: function () {
    return ({contact: {firstName: "first", lastName: "last", phone: "1244125"}});
  },
  handleChange: function (key,event) {
    console.log(key,event.target.value);

    //way 1 
    //var updatedContact = JSON.parse(JSON.stringify(this.state.contact));
    //updatedContact[key] = event.target.value;

    //way 2 (Recommended)
    var updatedContact = React.addons.update(this.state.contact, {
        [key] : {$set: event.target.value}
    });
    this.setState({contact: updatedContact});
  },
  render: function () {
    return (
        <div>
          <input type="text" onChange={this.handleChange.bind(this,"firstName")} value={this.state.contact.firstName}/>
          <input type="text" onChange={this.handleChange.bind(this,"lastName")} value={this.state.contact.lastName}/>
          <input type="text" onChange={this.handleChange.bind(this,"phone")} value={this.state.contact.phone}/>
        </div>
      );
    }
});

ReactDOM.render(
  <Component />,
  document.getElementById('container')
);
2
Mark

Hier ist eine generische;

handleChange = (input) => (event) => {
    this.setState({
        ...this.state,
        [input]: event.target.value
    });
}

Und so verwenden;

<input handleChange ={this.handleChange("phone")} value={this.state.phone}/>
1
MmtBkn

Der ordentlichste Ansatz

Hier ist ein Ansatz, den ich in meiner einfachen Anwendung verwendet habe. Dies ist der empfohlene Ansatz in React und es ist wirklich ordentlich und sauber. Es ist sehr nahe an der Antwort von ArneHugo und ich danke auch hm. Die Idee ist eine Mischung davon und reagiert auf Formulare. Wir können das name-Attribut jeder Formulareingabe verwenden, um den spezifischen propertyName abzurufen und den Status basierend darauf zu aktualisieren. Dies ist mein Code in ES6 für das obige Beispiel:

class ContactEdit extends React.Component {

  handleChangeFor = (event) => {
    const name = event.target.name;
    const value = event.target.value;
    const { contact } = this.state;
    const newContact = {
      ...contact,
      [name]: value
    };
    this.setState({ contact: newContact });
  }

  render() {
    return (
      <div>
        <input type="text" name="firstName" onChange={this.handleChangeFor} />
        <input type="text" name="lastName" onChange={this.handleChangeFor}/>
        <input type="text" name="phone" onChange={this.handleChangeFor}/>
      </div>
    );
  }
}

Die Unterschiede:

  • Wir müssen den Status nicht als Wertattribut zuweisen. Es wird kein Wert benötigt
  • Die onChange-Methode muss kein Argument innerhalb des Funktionsaufrufs enthalten, da stattdessen das Namensattribut verwendet wird
  • Wir deklarieren den Namen und den Wert jeder Eingabe im begening und setzen sie ein, um den Status ordnungsgemäß im Code festzulegen, und verwenden Namen als Name, da es sich um ein Attribut handelt.

Wir haben hier weniger Code und es ist ein kluger Weg, jegliche Art von Eingaben aus dem Formular zu erhalten, da das Namensattribut für jede Eingabe einen eindeutigen Wert hat. Sehen Sie ein funktionierendes Beispiel Ich habe CodPen für meine experimentelle Bloganwendung in einem frühen Stadium. 

1
azad6026

<input> -Elemente haben oft eine Eigenschaft namens name . Wir können auf diese name -Eigenschaft über das Ereignisobjekt zugreifen, das wir von einem Event-Handler erhalten:

Einen allgemeinen Änderungshandler schreiben

constructor () {
    super();
    this.state = {
      name: '',
      age: ''
    };
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange (evt) {      
    this.setState({ [evt.target.name]: evt.target.value });
  }

render () {
    return (
      <form>

        <label>Name</label>
        <input type="text" name="name" onChange={this.handleChange} />

        <label>Age</label>
        <input type="text" name="age" onChange={this.handleChange} />

      </form>
    );
  }

Quelle

0
Dhruv Raval
handleChange(event){
    this.setState({[event.target.name]:event.target.value});
    this.setState({[event.target.name]:event.target.value});
  }
0
Karan Chunara