Ottieni i dati del modulo in ReactJS


200

Ho una forma semplice nella mia renderfunzione, in questo modo:

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 ?
}

Cosa devo scrivere nel mio handleLogin: function() { ... }per accedere Emaile Passwordcampi?


11
@ssorallen Che assurdità è questa? Il richiedente potrebbe creare una SPA e probabilmente non desidera che il modulo venga inviato come un normale modulo HTML. Se lo desiderassero, definirebbero un'azione e rimuoveranno il gestore eventi.
Developerbmw,

6
Nota: è necessario gestire onSubmitil modulo anziché fare clic sul pulsante, in questo modo si gestirà anche l'utente che invia il modulo premendo Invio.
Developerbmw,

10
A <form>con a <button>o <input>con type=submitverrà inviato quando l'utente preme Invio in uno dei moduli <input type=text>. Se si fa affidamento su uno onClickdei pulsanti, l'utente deve fare clic sul pulsante o focalizzarlo e premere Invio / Barra spaziatrice. L'uso onSubmitconsentirà entrambi i casi d'uso. Quando i moduli non supportano Invio per l'invio, possono sentirsi non funzionanti.
Ross Allen,

Risposte:


167

Utilizzare gli changeeventi sugli input per aggiornare lo stato del componente e accedervi in 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);
}

Violino di lavoro .

Inoltre, leggi i documenti, c'è un'intera sezione dedicata alla gestione dei moduli : i moduli

In precedenza potresti anche utilizzare il mixin di helper di databinding bidirezionale di React per ottenere la stessa cosa, ma ora è deprecato a favore dell'impostazione del valore e del gestore di modifica (come sopra):

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>
    );
  }
});

La documentazione è qui: Helpers di rilegatura bidirezionali .


3
Per imitare correttamente la funzionalità di valueLink, il tuo primo esempio dovrebbe impostare gli valueelementi di input. Senza questo, i valori sono "incontrollati" in termini di React. <input ... value={this.state.password}>.
Ross Allen,

10
puoi anche usare un onSubmit con il modulo anziché onClick con il pulsante
sai

60
Perché usare uno stato per ogni elemento del modulo? Qualcun altro pensa che questo sia un cattivo modello?
Eveevans,

6
Sembra che il valore sia obsoleto
Matt Broekhuis,

3
Questo non sta memorizzando la password in chiaro sul lato client per tutto il tempo? Non sembra molto appropriato per un campo password.
NewbiZ,

166

Ci sono alcuni modi per farlo:

1) Ottieni valori dalla matrice di elementi del modulo per indice

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

2) Utilizzo dell'attributo name 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) Utilizzo di rif

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

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

Esempio completo

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
Questa è una risposta fantastica Grazie per aver elencato diversi modi per farlo.
Beau Smith,

L'opzione 2 non funziona per me. Non ci sono "elementi" di proprietà né "nome utente", anche se il nome del mio input è "nome utente"
Madacol

@Madacol questo può succedere se hai qualche input con lo stesso nome
Aliaksandr Sushkevich,

45

Un approccio alternativo consiste nell'utilizzare l' refattributo e fare riferimento ai valori con this.refs. Qui c'è un semplice esempio:

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

Ulteriori informazioni sono disponibili nei documenti di React: https://facebook.github.io/react/docs/more-about-refs.html#the-ref-string-attribute

Per molte delle ragioni descritte in Come si usano i pulsanti di opzione in React? questo approccio non è sempre il migliore, ma presenta un'alternativa utile in alcuni casi semplici.


1
Questa soluzione è davvero migliore e non era disponibile al momento delle domande o è un modo "brutto"?
Wagner Leonardi,

4
in realtà non hai bisogno di React.findDOMNode this.refs.theInput già un nodo html
Fareed Alnamrouti

23

Un modo semplice per gestire i riferimenti:

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
Questo metodo un giorno sarà deprecato. I riferimenti devono essere utilizzati solo con callback e non stringhe. Per maggiori dettagli: facebook.github.io/react/docs/refs-and-the-dom.html
David Labbe

Freddo! :) Mi piace usare Object.keys()seguito per map()questo:Object.keys(this.refs).map(field => formData[field] = this.refs[field].value)
Francis Rodrigues il

Sì, i riferimenti alla stringa sono obsoleti. Un modo migliore per farlo adesso è usare il callback onChange. Se vuoi ancora usare refs puoi usare questa sintassi:<input type="text" ref={(input) => { this.textInput = input; }} />
E. Fortes,

I @ E.Fortes, puoi per favore spiegare il metodo di callback onChange? Grazie mille se lo farai. Per favore taggami in modo che sarò informato della tua risposta.
Simona Adriani,

un modo semplice sarebbe (scusate se il formattatore del codice non funziona): class NameForm estende React.Component {constructor (props) {super (props); 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,

23

Aggiungendo alla risposta di 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>
    );
  }
}

Vedi questo articolo medio: Come gestire i moduli con Just React

Questo metodo ottiene i dati del modulo solo quando si preme il pulsante Invia. IMO molto più pulito!


Risposta perfetta 👌
Michal,

16

È possibile passare il onClickgestore eventi sul pulsante a un onSubmitgestore nel modulo:

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>
      );
    },

Quindi è possibile utilizzare FormDataper analizzare il modulo (e costruire un oggetto JSON dalle sue voci se lo si desidera).

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
}

Eseguendo questo plus 'console.log (utente);' dà un oggetto senza valore utilizzabile! Qualche opinione?
M al

@MahdiRafatjah ¯ \ _ (ツ) _ / ¯ - funziona in questo violino: jsfiddle.net/mschock/exvko2Lf
Michael Schock

un mio amico mi ha fatto riferimento per reagire al documento e lo stanno facendo in questo modo. reagisci.componenti
M al

1
bello, sembra molto più pulito =)
Michael Schock,

13

Suggerirei il seguente approccio:

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>
        )
    }

}

Se non si reinvia il componente, come è possibile impostare il valore di ciascun elemento in base allo stato corrente? ad es. "value = {this.state. destination}". Inoltre non è possibile eseguire reagiscono convalide sul modulo se il tuo non è rerendering
Avishay28

13

Se tutti i tuoi input / textarea hanno un nome, puoi filtrare tutto da event.target:

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

Forma totalmente incontrollata 😊 senza metodi onChange, valore, defaultValue ...


12

Per coloro che non vogliono usare ref e resettare lo stato con un OnChangeevento, puoi semplicemente usare l'handle di OnSubmit e scorrere ciclicamente l' FormDataoggetto. Questo esempio utilizza React Hooks:

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>)
        }

Ottima risposta, ma un pignolo potrebbe rimuovere la var var altrimenti soluzione perfetta!
Louis345,

5

Inoltre, anche questo può essere usato.

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
Includi una spiegazione del perché questa risposta è la strada giusta da percorrere.
Tim Hutchison,

1
Uso un solo metodo per modificare il modulo di testo
Yurii Kosygin,

La password può essere vista negli strumenti di sviluppo degli sviluppatori, un po 'un problema di sicurezza?
Neil,

5

Dai ai tuoi input ref in questo modo

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

allora puoi accedervi dal tuo handleLogin come soo

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

5

Esempio più chiaro con la distruzione di 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 molti eventi in javascript, abbiamo eventche danno un oggetto incluso quale evento è accaduto e quali sono i valori, ecc ...

Questo è ciò che usiamo anche con i moduli in ReactJs ...

Quindi nel tuo codice imposti lo stato sul nuovo valore ... qualcosa del genere:

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;

Anche questo è l'esempio di modulo in React v.16, proprio come riferimento per il modulo che creerai in futuro:

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

Uso in questo modo lo stato di React Component:

<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>

Immagine di output allegata qui


Fornisci anche una spiegazione.
BlackBeard

2
Proverò a spiegarlo, che ho trovato geniale. Nella funzione handleSubmit () stai costruendo un oggetto (formData) in cui la chiave è l'attributo 'ref' di ogni input nel form (l'istruzione 'formData [data]') e il valore è il valore dell'input con questo attributo 'ref' (l'istruzione 'this.refs [data] .value'). Con 'formData [data] = this.refs [data] .value' stai costruendo questo oggetto. Stai letteralmente dicendo: formData ['username'] = (il valore dell'input del nome utente) e formData ['password'] = (il valore dell'input della password) L'output sarà: {user: 'blablabla', password: 'xxx '}
Simona Adriani,

Grazie @ SimonaAdriani per la tua spiegazione.
Milan Panigrahi,

2

Questo potrebbe aiutare gli utenti Meteor (v1.3):

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) dovrebbe essere giusto: this.submitForm
rekarnar

Errore: i componenti della funzione senza stato non possono avere riferimenti.
holms

Stai usando Meteor (v1.3)?
Joe L.

1

Migliorare l'esperienza dell'utente; quando l'utente fa clic sul pulsante di invio, puoi provare a ottenere il modulo per mostrare prima un messaggio di invio. Una volta ricevuta una risposta dal server, è possibile aggiornare il messaggio di conseguenza. Raggiungiamo questo obiettivo in React concatenando gli stati. Vedi codepen o snippet di seguito:

Il seguente metodo consente di modificare il primo stato:

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

Non appena React mostra sullo schermo il messaggio di invio sopra, chiamerà il metodo che invierà i dati del modulo al server: this.sendFormData (). Per semplicità ho aggiunto un setTimeout per imitare questo.

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, il metodo this.setState () esegue il rendering di un componente con nuove proprietà. Quindi puoi anche aggiungere un po 'di logica nel metodo render () del componente form che si comporterà in modo diverso a seconda del tipo di risposta che otteniamo dal server. Per esempio:

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

Se hai più occorrenze di un nome di elemento, devi usare forEach ().

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);
};

Nota che in questo caso i dels sono RadioNodeList, non un array e non sono Iterable. ForEach () è un metodo incorporato della classe list. Non potrai usare una mappa () o ridurre () qui.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.