Formulardaten in ReactJS abrufen


199

Ich habe eine einfache Form in meiner renderFunktion, wie folgt:

render : function() {
      return (
        <form>
          <input type="text" name="email" placeholder="Email" />
          <input type="password" name="password" placeholder="Password" />
          <button type="button" onClick={this.handleLogin}>Login</button>
        </form>
      );
    },
handleLogin: function() {
   //How to access email and password here ?
}

Was soll ich in meine handleLogin: function() { ... }Zugangs- Emailund PasswordFelder schreiben ?


11
@ssorallen Was für ein Unsinn ist das? Der Fragesteller könnte ein SPA erstellen und möchte wahrscheinlich nicht, dass das Formular wie ein normales HTML-Formular gesendet wird . Wenn sie dies wollten, würden sie eine Aktion definieren und den Ereignishandler entfernen.
Entwickler

6
Hinweis: Sie sollten onSubmitdas Formular und nicht den Klick auf die Schaltfläche bearbeiten. Auf diese Weise können Sie auch den Benutzer behandeln, der das Formular durch Drücken der Eingabetaste sendet.
Entwickler

10
Ein <form>mit einem <button>oder <input>mit type=submitwird gesendet, wenn der Benutzer in einem der Formulare die Eingabetaste drückt <input type=text>. Wenn Sie sich auf onClickeine Schaltfläche verlassen, muss der Benutzer auf die Schaltfläche klicken oder sie fokussieren und die Eingabetaste / Leertaste drücken. Mit onSubmitwird beide Anwendungsfälle aktiviert. Wenn Formulare die Eingabe von Enter nicht unterstützen, können sie sich beschädigt fühlen.
Ross Allen

Antworten:


165

Verwenden Sie die changeEreignisse an den Eingaben, um den Status der Komponente zu aktualisieren und darauf zuzugreifen handleLogin:

handleEmailChange: function(e) {
   this.setState({email: e.target.value});
},
handlePasswordChange: function(e) {
   this.setState({password: e.target.value});
},
render : function() {
      return (
        <form>
          <input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleEmailChange} />
          <input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handlePasswordChange}/>
          <button type="button" onClick={this.handleLogin}>Login</button>
        </form>);
},
handleLogin: function() {
    console.log("EMail: " + this.state.email);
    console.log("Password: " + this.state.password);
}

Arbeits Geige .

Lesen Sie auch die Dokumente. Es gibt einen ganzen Abschnitt, der der Formularbearbeitung gewidmet ist: Formulare

Früher konnten Sie auch das Zwei-Wege-Hilfemixin für die Datenbindung von React verwenden, um dasselbe zu erreichen. Jetzt ist es jedoch veraltet, den Wert festzulegen und den Handler zu ändern (wie oben):

var ExampleForm = React.createClass({
  mixins: [React.addons.LinkedStateMixin],
  getInitialState: function() {
    return {email: '', password: ''};
  },
  handleLogin: function() {
    console.log("EMail: " + this.state.email);
    console.log("Password: " + this.state.password);
  },
  render: function() {
    return (
      <form>
        <input type="text" valueLink={this.linkState('email')} />
        <input type="password" valueLink={this.linkState('password')} />
        <button type="button" onClick={this.handleLogin}>Login</button>
      </form>
    );
  }
});

Die Dokumentation finden Sie hier: Zweiwege-Bindungshelfer .


3
Um die Funktionalität von korrekt nachzuahmen valueLink, sollte Ihr erstes Beispiel valuedie Eingabeelemente festlegen . Ohne das sind die Werte in Bezug auf die Reaktion "unkontrolliert" . <input ... value={this.state.password}>.
Ross Allen

10
Sie können auch ein onSubmit mit dem Formular anstelle von onClick mit der Schaltfläche verwenden
sai

58
Warum für jedes Element des Formulars einen Status verwenden? Glaubt sonst noch jemand, dass dies ein schlechtes Muster ist?
Evaevans

6
Sieht aus wie valueLink veraltet ist
Matt Broekhuis

3
Wird das Passwort nicht für die gesamte Zeit im Klartext auf der Clientseite gespeichert? Das scheint für ein Passwortfeld nicht wirklich angemessen zu sein.
NewbiZ

166

Es gibt einige Möglichkeiten, dies zu tun:

1) Ruft Werte aus dem Array von Formularelementen nach Index ab

handleSubmit = (event) => {
  event.preventDefault();
  console.log(event.target[0].value)
}

2) Mit Namen Attribute in html

handleSubmit = (event) => {
  event.preventDefault();
  console.log(event.target.elements.username.value) // from elements property
  console.log(event.target.username.value)          // or directly
}

<input type="text" name="username"/>

3) Verwenden von Refs

handleSubmit = (event) => {
  console.log(this.inputNode.value)
}

<input type="text" name="username" ref={node => (this.inputNode = node)}/>

Vollständiges Beispiel

class NameForm extends React.Component {
  handleSubmit = (event) => {
    event.preventDefault()
    console.log(event.target[0].value)
    console.log(event.target.elements.username.value)
    console.log(event.target.username.value)
    console.log(this.inputNode.value)
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input
            type="text"
            name="username"
            ref={node => (this.inputNode = node)}
          />
        </label>
        <button type="submit">Submit</button>
      </form>
    )
  }
}

1
Dies ist eine fantastische Antwort. Vielen Dank, dass Sie mehrere Möglichkeiten aufgeführt haben, dies zu tun.
Beau Smith

Option 2 funktioniert bei mir nicht. Es gibt keine Eigenschaft "Elemente" oder "Benutzername", obwohl der Name meiner Eingabe "Benutzername" ist
Madacol

@ Madacol dies kann passieren, wenn Sie einige Eingaben mit dem gleichen Namen haben
Aliaksandr Sushkevich

45

Ein alternativer Ansatz besteht darin, das refAttribut zu verwenden und die Werte mit zu referenzieren this.refs. Hier ist ein einfaches Beispiel:

render: function() {
    return (<form onSubmit={this.submitForm}>
        <input ref="theInput" />
    </form>);
},
submitForm: function(e) {
    e.preventDefault();
    alert(React.findDOMNode(this.refs.theInput).value);
}

Weitere Informationen finden Sie in den React-Dokumenten: https://facebook.github.io/react/docs/more-about-refs.html#the-ref-string-attribute

Aus vielen der unter Wie verwende ich Optionsfelder in React? Dieser Ansatz ist nicht immer der beste, bietet jedoch in einigen einfachen Fällen eine nützliche Alternative.


1
Ist diese Lösung wirklich besser und war zur Fragestunde nicht verfügbar oder ist sie ein "hässlicher" Weg?
Wagner Leonardi

4
Eigentlich brauchen Sie React.findDOMNode this.refs.theInput nicht bereits als HTML-Knoten
Fareed Alnamrouti

23

Ein einfacher Weg, um mit Refs umzugehen:

class UserInfo extends React.Component {

  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleSubmit(e) {
    e.preventDefault();
    
    const formData = {};
    for (const field in this.refs) {
      formData[field] = this.refs[field].value;
    }
    console.log('-->', formData);
  }

  render() {
    return (
        <div>
          <form onSubmit={this.handleSubmit}>
            <input ref="phone" className="phone" type='tel' name="phone"/>
            <input ref="email" className="email" type='tel' name="email"/>
            <input type="submit" value="Submit"/>
          </form>
        </div>
    );
  }
}

export default UserInfo;


2
Diese Methode wird eines Tages in der Zukunft veraltet sein. Refs dürfen nur mit Rückrufen und nicht mit Strings verwendet werden. Für weitere Informationen: facebook.github.io/react/docs/refs-and-the-dom.html
David Labbe

Cool! :) Ich benutze gerne Object.keys()folgende für map():Object.keys(this.refs).map(field => formData[field] = this.refs[field].value)
Francis Rodrigues

Ja, die Zeichenfolgenreferenzen sind veraltet. Eine bessere Möglichkeit, dies jetzt zu tun, ist die Verwendung des onChange-Rückrufs. Wenn Sie weiterhin Refs verwenden möchten, können Sie diese Synktax verwenden:<input type="text" ref={(input) => { this.textInput = input; }} />
E. Fortes

I @ E.Fortes, können Sie bitte die onChange-Rückrufmethode erläutern? Vielen Dank, wenn Sie so wollen. Bitte markieren Sie mich, damit ich über Ihre Antwort informiert werde.
Simona Adriani

Ein einfacher Weg wäre (sorry, der Code-Formatierer funktioniert nicht): Klasse NameForm erweitert React.Component {Konstruktor (Requisiten) {Super (Requisiten); this.state = {value: ''}; this.handleChange = this.handleChange.bind (this); } handleChange (event) {this.setState ({value: event.target.value}); } render () {return (<form> <label> Name: <input type = "text" value = {this.state.value} onChange = {this.handleChange} /> </ label> </ form>); }}
E. Fortes

21

Hinzu kommt die Antwort von Michael Schock:

class MyForm extends React.Component {
  constructor() {
    super();
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleSubmit(event) {
    event.preventDefault();
    const data = new FormData(event.target);

    console.log(data.get('email')); // reference by form input's `name` tag

    fetch('/api/form-submit-url', {
      method: 'POST',
      body: data,
    });
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label htmlFor="username">Enter username</label>
        <input id="username" name="username" type="text" />

        <label htmlFor="email">Enter your email</label>
        <input id="email" name="email" type="email" />

        <label htmlFor="birthdate">Enter your birth date</label>
        <input id="birthdate" name="birthdate" type="text" />

        <button>Send data!</button>
      </form>
    );
  }
}

Siehe diesen mittleren Artikel: So behandeln Sie Formulare mit Just React

Diese Methode ruft Formulardaten nur ab, wenn die Schaltfläche Senden gedrückt wird. Viel sauberer IMO!


Perfekte Antwort. 👌
Michal

16

Sie können den onClickEreignishandler auf der Schaltfläche auf einen onSubmitHandler im Formular umstellen :

render : function() {
      return (
        <form onSubmit={this.handleLogin}>
          <input type="text" name="email" placeholder="Email" />
          <input type="password" name="password" placeholder="Password" />
          <button type="submit">Login</button>
        </form>
      );
    },

Anschließend können Sie FormDatadas Formular analysieren (und ein JSON-Objekt aus seinen Einträgen erstellen, wenn Sie möchten).

handleLogin: function(e) {
   const formData = new FormData(e.target)
   const user = {}

   e.preventDefault()

   for (let entry of formData.entries()) {
       user[entry[0]] = entry[1]
   }

   // Do what you will with the user object here
}

Ausführen dieses Plus 'console.log (Benutzer);' gibt ein Objekt ohne Nutzwert! Irgendeine Meinung?
M am

@ MahdiRafatjah ¯ \ _ (ツ) _ / ¯ - es funktioniert in dieser Geige: jsfiddle.net/mschock/exvko2Lf
Michael Schock

Ein Freund von mir hat mich auf ein Reaktionsdokument verwiesen und sie machen es so: reactjs.org/docs/forms.html#controlled-components
M am

1
schön, das scheint viel sauberer =)
Michael Schock

13

Ich würde den folgenden Ansatz vorschlagen:

import {Autobind} from 'es-decorators';

export class Form extends Component {

    @Autobind
    handleChange(e) {
        this.setState({[e.target.name]: e.target.value});
    }

    @Autobind
    add(e) {
        e.preventDefault();
        this.collection.add(this.state);
        this.refs.form.reset();
    }

    shouldComponentUpdate() {
        return false;
    }

    render() {
        return (
            <form onSubmit={this.add} ref="form">
                <input type="text" name="desination" onChange={this.handleChange}/>
                <input type="date" name="startDate" onChange={this.handleChange}/>
                <input type="date" name="endDate" onChange={this.handleChange}/>
                <textarea name="description" onChange={this.handleChange}/>
                <button type="submit">Add</button>
            </form>
        )
    }

}

13

Wenn alle Ihre Eingaben / Textbereiche einen Namen haben, können Sie alle aus event.target filtern:

onSubmit(event){
  const fields = Array.prototype.slice.call(event.target)
      .filter(el => el.name)
      .reduce((form, el) => ({
        ...form,
        [el.name]: el.value,
      }), {})
}

Völlig unkontrollierte Form 😊 ohne onChange-Methoden, Wert, defaultValue ...


12

Für diejenigen, die ref nicht verwenden und den Status mit OnChangeevent zurücksetzen möchten , können Sie einfach das OnSubmit-Handle verwenden und das FormDataObjekt durchlaufen . In diesem Beispiel werden React Hooks verwendet:

const LoginPage = () =>{
    const handleSubmit = (event) => {
        const formData = new FormData(event.target);
        event.preventDefault();
        for (var [key, value] of formData.entries()) {
            console.log(key, value);
        }
    }

    return (
        <div>
        <form onSubmit={
        handleSubmit
        }

        >
        <input type="text" name="username" placeholder="Email" />
        <input type="password" name="password"
        placeholder="Password" />
        <button type="submit">Login</button>
        </form>
        </div>)
        }

Tolle Antwort, aber mit einem Nitpick könnten Sie die var ansonsten perfekte Lösung entfernen!
Louis345

5

Auch dies kann verwendet werden.

handleChange: function(state,e) {
  this.setState({[state]: e.target.value});
},
render : function() {
  return (
    <form>
      <input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleChange.bind(this, 'email')} />
      <input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handleChange.bind(this, 'password')}/>
      <button type="button" onClick={this.handleLogin}>Login</button>
    </form>
  );
},
handleLogin: function() {
  console.log("EMail: ", this.state.email);
  console.log("Password: ", this.state.password);
}

4
Bitte geben Sie eine Erklärung an, warum diese Antwort der richtige Weg ist.
Tim Hutchison

1
Ich benutze nur eine Methode, um die Textform zu ändern
Yurii Kosygin

Das Passwort kann in React Dev Tools gesehen werden, ein bisschen ein Sicherheitsproblem?
Neil

5

Geben Sie Ihre Eingaben ref so

<input type="text" name="email" placeholder="Email" ref="email" />
<input type="password" name="password" placeholder="Password" ref="password" />

dann können Sie wie soo in Ihrem handleLogin darauf zugreifen

handleLogin: function(e) {
   e.preventDefault();
    console.log(this.refs.email.value)
    console.log(this.refs.password.value)
}

5

Klareres Beispiel für die Zerstörung von es6

class Form extends Component {
    constructor(props) {
        super(props);
        this.state = {
            login: null,
            password: null,
            email: null
        }
    }

    onChange(e) {
        this.setState({
            [e.target.name]: e.target.value
        })
    }

    onSubmit(e) {
        e.preventDefault();
        let login = this.state.login;
        let password = this.state.password;
        // etc
    }

    render() {
        return (
            <form onSubmit={this.onSubmit.bind(this)}>
                <input type="text" name="login" onChange={this.onChange.bind(this)} />
                <input type="password" name="password" onChange={this.onChange.bind(this)} />
                <input type="email" name="email" onChange={this.onChange.bind(this)} />
                <button type="submit">Sign Up</button>
            </form>
        );
    }
}


4

In vielen Ereignissen in Javascript haben wir, eventdie ein Objekt angeben, einschließlich welches Ereignis passiert ist und welche Werte usw.

Das verwenden wir auch mit Formularen in ReactJs ...

Also setzen Sie in Ihrem Code den Status auf den neuen Wert ... ungefähr so:

class UserInfo extends React.Component {

  constructor(props) {
    super(props);
    this.handleLogin = this.handleLogin.bind(this);
  }

  handleLogin(e) {
    e.preventDefault();
    for (const field in this.refs) {
      this.setState({this.refs[field]: this.refs[field].value});
    }
  }

  render() {
    return (
        <div>
          <form onSubmit={this.handleLogin}>
            <input ref="email" type="text" name="email" placeholder="Email" />
            <input ref="password" type="password" name="password" placeholder="Password" />
            <button type="button">Login</button>
          </form>
        </div>
    );
  }
}

export default UserInfo;

Dies ist auch das Formularbeispiel in React v.16, nur als Referenz für das Formular, das Sie in Zukunft erstellen:

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

4

Ich benutze so mit React Component state:

<input type="text" name='value' value={this.state.value} onChange={(e) => this.handleChange(e)} />

handleChange(e){
   this.setState({[e.target.name]: e.target.value})
}`

3
 onChange(event){
     console.log(event.target.value);
  }
  handleSubmit(event){ 
    event.preventDefault();
    const formData = {};
      for (const data in this.refs) {
        formData[data] = this.refs[data].value;
      }
    console.log(formData);
  }



 <form onSubmit={this.handleSubmit.bind(this)}>
  <input type="text" ref="username" onChange={this.onChange} className="form-control"/>
  <input type="text" ref="password" onChange={this.onChange} className="form-control"/>
  <button type="submit" className="btn-danger btn-sm">Search</button>
 </form>

Ausgabebild hier angehängt


Bitte geben Sie auch eine Erklärung an.
BlackBeard

2
Ich werde versuchen, dies zu erklären, was ich brillant fand. In der Funktion handleSubmit () erstellen Sie ein Objekt (formData), in dem der Schlüssel das Attribut 'ref' jeder Eingabe im Formular ist (die Anweisung 'formData [data]') und der Wert der Wert der Eingabe ist mit diesem Attribut 'ref' (die Anweisung 'this.refs [data] .value'). Mit 'formData [data] = this.refs [data] .value' erstellen Sie dieses Objekt. Sie sagen wörtlich: formData ['Benutzername'] = (der Wert der Eingabe des Benutzernamens) und formData ['Passwort'] = (der Wert der Passworteingabe) Die Ausgabe lautet: {Benutzer: 'blablabla', Passwort: 'xxx '}
Simona Adriani

Vielen Dank an SimonaAdriani für Ihre Erklärung.
Milan Panigrahi

2

Dies könnte Meteor (v1.3) -Nutzern helfen:

render: function() {
    return (
        <form onSubmit={this.submitForm.bind(this)}>
            <input type="text" ref="email" placeholder="Email" />
            <input type="password" ref="password" placeholder="Password" />
            <button type="submit">Login</button>
        </form>
    );
},
submitForm: function(e) {
    e.preventDefault();
    console.log( this.refs.email.value );
    console.log( this.refs.password.value );
}

1
this.submitForm.bind (this) sollte nur sein: this.submitForm
rekarnar

Fehler: Statuslose Funktionskomponenten können keine Refs haben.
Holms

Verwenden Sie Meteor (v1.3)?
Joe L.

1

Verbesserung der Benutzererfahrung; Wenn der Benutzer auf die Schaltfläche "Senden" klickt, können Sie versuchen, das Formular so zu gestalten, dass zuerst eine sendende Nachricht angezeigt wird. Sobald wir eine Antwort vom Server erhalten haben, kann er die Nachricht entsprechend aktualisieren. Dies erreichen wir in React durch Verketten von Status. Siehe Codepen oder Snippets unten:

Die folgende Methode führt die erste Statusänderung durch:

handleSubmit(e) {
    e.preventDefault();
    this.setState({ message: 'Sending...' }, this.sendFormData);
}

Sobald React die obige Sending-Nachricht auf dem Bildschirm anzeigt, wird die Methode aufgerufen, mit der die Formulardaten an den Server gesendet werden: this.sendFormData (). Der Einfachheit halber habe ich ein setTimeout hinzugefügt, um dies nachzuahmen.

sendFormData() {
  var formData = {
      Title: this.refs.Title.value,
      Author: this.refs.Author.value,
      Genre: this.refs.Genre.value,
      YearReleased: this.refs.YearReleased.value};
  setTimeout(() => { 
    console.log(formData);
    this.setState({ message: 'data sent!' });
  }, 3000);
}

In React rendert die Methode this.setState () eine Komponente mit neuen Eigenschaften. Sie können also auch eine Logik in der render () -Methode der Formularkomponente hinzufügen, die sich je nach Art der Antwort, die wir vom Server erhalten, unterschiedlich verhält. Zum Beispiel:

render() {
  if (this.state.responseType) {
      var classString = 'alert alert-' + this.state.type;
      var status = <div id="status" className={classString} ref="status">
                     {this.state.message}
                   </div>;
  }
return ( ...

Codepen


1

Wenn ein Elementname mehrfach vorkommt, müssen Sie forEach () verwenden.

html

  <input type="checkbox" name="delete" id="flizzit" />
  <input type="checkbox" name="delete" id="floo" />
  <input type="checkbox" name="delete" id="flum" />
  <input type="submit" value="Save"  onClick={evt => saveAction(evt)}></input>

js

const submitAction = (evt) => {
  evt.preventDefault();
  const dels = evt.target.parentElement.delete;
  const deleted = [];
  dels.forEach((d) => { if (d.checked) deleted.push(d.id); });
  window.alert(deleted.length);
};

Beachten Sie, dass die Dels in diesem Fall eine RadioNodeList, kein Array und keine Iterable sind. ForEach () ist eine integrierte Methode der Listenklasse. Sie können hier keine map () oder redu () verwenden.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.