Отримати дані форми в ReactJS


199

Я маю просту форму у своїй renderфункції:

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

Що потрібно написати в моєму handleLogin: function() { ... }доступі Emailта Passwordполях?


11
@ssorallen Що це за дурниці? Автор запитувача може будувати SPA і, ймовірно , не хоче, щоб форма надсилалася як звичайна форма HTML. Якби вони цього хотіли, вони визначили б дію та видалили обробник подій.
developerbmw

6
Примітка: вам слід обробляти onSubmitформу, а не натискання кнопки - таким чином ви також будете обробляти користувача, який подає форму, натискаючи клавішу Enter.
developerbmw

10
А <form>з <button>або <input>з type=submitбуде надсилатися, коли користувач натисне клавішу Enter у будь-якій формі <input type=text>. Якщо ви покладаєтесь на onClickкнопку, користувач повинен натиснути кнопку або сфокусувати її та натиснути клавішу Enter / Пробіл. Використання onSubmitдозволить обидва випадки використання. Якщо форми не підтримують Enter для надсилання, вони можуть почуватися зламаними.
Росс Аллен

Відповіді:


167

Використовуйте changeподії на входах для оновлення стану компонента та доступу до нього у 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);
}

Робоча скрипка .

Крім того, прочитайте документи, є цілий розділ, присвячений обробці форм : Форми

Раніше ви також могли використовувати двосторонній помічник допоміжного зв’язку React для досягнення того ж самого, але тепер це застаріло на користь встановлення значення та зміни обробника (як вище):

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

Документація знаходиться тут: Двосторонні зв'язуючі помічники .


3
Щоб правильно імітувати функціональність valueLink, у першому прикладі слід встановити valueвхідні елементи. Без цього значення "контрольовані" в термінах React. <input ... value={this.state.password}>.
Росс Аллен

10
ви також можете використовувати onSubmit із формою замість onClick з кнопкою
sai

58
Навіщо використовувати стан для кожного елемента форми? Хтось ще вважає це поганою схемою?
eveevans

6
Схоже, що значення "Посилання" застаріле
Метт Брукхуйс

3
Це не зберігання пароля в чистому тексті на стороні клієнта протягом усього часу? Це не здається дійсно підходящим для поля пароля.
NewbiZ

166

Є кілька способів зробити це:

1) Отримати значення з масиву елементів форми за індексом

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

2) Використання атрибута name в 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) Використання реф

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

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

Повний приклад

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
Це фантастична відповідь. Дякуємо, що перерахували кілька способів зробити це.
Бо Сміт

Варіант 2 не працює для мене. Немає властивостей "елементів", ані "ім'я користувача", хоча ім'я мого входу є "ім'я користувача"
Madacol,

@Madacol це може статися, якщо у вас є кілька входів з такою ж назвою
Олександр Сушкевич,

45

Альтернативний підхід - використовувати refатрибут та посилатись на значення this.refs. Ось простий приклад:

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

Більше інформації можна знайти в документах React: https://facebook.github.io/react/docs/more-about-refs.html#the-ref-string-attribute

З багатьох причин, описаних у розділі Як використовувати перемикачі в React? такий підхід не завжди найкращий, але він є корисною альтернативою в деяких простих випадках.


1
Це рішення дійсно краще і не було доступне в питання, або це "потворний" спосіб?
Вагнер Леонарді

4
насправді вам не потрібен React.findDOMNode this.refs.theInput вже html-вузол
Fareed Alnamrouti

23

Найпростіший спосіб вирішити питання:

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
Цей метод колись у майбутньому буде застарілим. Відмовки використовуються лише для зворотного зв'язку, а не для рядків. Детальніше: facebook.github.io/react/docs/refs-and-the-dom.html
Девід Лаббе

Класно! :) Мені подобається використовувати Object.keys()наступне map():Object.keys(this.refs).map(field => formData[field] = this.refs[field].value)
Френсіс Родрігес

Так, строкові параметри застаріли. Кращий спосіб зробити це прямо зараз - використовувати зворотний виклик onChange. Якщо ви все ще хочете використовувати рефлекси, ви можете скористатися цим синтаксисом:<input type="text" ref={(input) => { this.textInput = input; }} />
E. Fortes

Я @ E.Fortes, можете пояснити, будь ласка, метод onChange? Дуже дякую, якщо хочете. Будь ласка, позначте мене, щоб я був повідомлений про вашу відповідь
Симона Адріані

простим способом було б (вибачте, формат коду не працює): клас NameForm розширює React.Component {конструктор (реквізит) {super (реквізит); this.state = {значення: ''}; this.handleChange = this.handleChange.bind (це); } handleChange (подія) {this.setState ({значення: event.target.value}); } render () {return (<form> <label> Ім'я: <input type = "text" value = {this.state.value} onChange = {this.handleChange} /> </label> </form>); }}
Е. Фортес

22

Додавання відповіді Майкла Шока:

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

Дивіться цю середню статтю: Як поводитися з формами просто реагувати

Цей метод отримує дані форми лише після натискання кнопки "Надіслати". Набагато чистіше ІМО!


Ідеальна відповідь. 👌
Міхал

16

Ви можете переключити onClickобробник подій на кнопку на onSubmitобробник форми:

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

Тоді ви можете скористатися FormDataдля розбору форми (і, якщо хочете, побудувати об’єкт JSON з його записів).

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
}

Запуск цього плюс 'console.log (користувач);' дає об’єкт без корисного значення! Якась думка?
М

@MahdiRafatjah ¯ \ _ (ツ) _ / ¯ - працює у цій скрипці: jsfiddle.net/mschock/exvko2Lf
Майкл Шок

мій друг направив мене на реакцію на документ, і вони роблять це так, як це reactjs.org/docs/forms.html#control-components
M

1
приємно, що здається набагато чистішим =)
Майкл Шок

13

Я б запропонував такий підхід:

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

}

Якщо ви не передаєте компонент, як ви можете встановити значення кожного елемента відповідно до поточного стану? наприклад, "value = {this.state. призначення}". Крім того, ви не можете запустити перевірку реакції на форму, якщо її не відтворюєте
Avishay28

13

Якщо всі ваші входи / textarea мають ім'я, ви можете відфільтрувати все з event.target:

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

Повністю неконтрольована форма 😊 без onChange методів, значення, defaultValue ...


12

Для тих, хто не бажає використовувати ref і скидати стан з OnChangeподією, ви можете просто скористатися простою ручкою OnSubmit і циклом через FormDataоб'єкт. У цьому прикладі використовується реактивні гачки:

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

Чудова відповідь, але нітпік ви могли б зняти вар інакше ідеальне рішення!
Louis345

5

Також і цим можна скористатися.

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
Будь ласка, додайте пояснення, чому ця відповідь є правильним шляхом.
Тім Хатчісон

1
Я використовую лише один метод для зміни текстової форми
Юрій Косигін

Пароль можна побачити в інструментах реагування розробників, проблемах із безпекою?
Ніл

5

Подайте свої вкладки таким чином

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

то ви можете отримати доступ до нього в ручці Вхід, як soo

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

5

Більш чіткий приклад з руйнуванням 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

Якщо ви використовуєте Redux у своєму проекті, ви можете розглянути можливість використання цього компонента вищого порядку https://github.com/erikras/redux-form .


4

У багатьох подіях у javascript ми eventнадаємо об'єкт, включаючи те, що відбулася подія та які значення, тощо.

Це те, що ми використовуємо і з формами в ReactJs ...

Отже, у своєму коді ви встановлюєте стан на нове значення ... приблизно так:

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;

Також це приклад форми в React v.16, так само як посилання на форму, яку ви створюєте в майбутньому:

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

Я використовую так, використовуючи стан 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>

Вихідне зображення додається тут


Будь ласка, надайте пояснення.
BlackBeard

2
Я спробую пояснити це, що мені здалося геніальним. У функції handleSubmit () ви будуєте об’єкт (formData), в якому ключ - атрибут 'ref' кожного вводу форми (вираз 'formData [дані]'), а значення - значення вводу з цим атрибутом 'ref' (вираз 'this.refs [data] .value'). За допомогою 'formData [data] = this.refs [data] .value' ви будуєте цей об’єкт. Ви говорите буквально: formData ['ім'я користувача'] = (значення вводу імені користувача) та formData ['пароль'] = (значення введення пароля) Вихід буде: {user: 'blablabla', пароль: 'xxx '}
Симона Адріані

Дякую @SimonaAdriani за пояснення.
Мілан Паніграхі

2

Це може допомогти користувачам 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.submitForm
rekarnar

Помилка: у функціональних компонентів без стану не може бути відповідей.
холм

Ви використовуєте Meteor (v1.3)?
Джо Л.

1

Поліпшення користувальницької роботи; коли користувач натискає кнопку надіслати, ви можете спробувати отримати форму, щоб спочатку показати повідомлення, що надсилає. Щойно ми отримаємо відповідь від сервера, він може оновити повідомлення відповідно. Ми досягаємо цього в React, прив'язуючи статуси. Дивіться кодек або фрагменти нижче:

Наступний метод робить першу зміну стану:

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

Як тільки React покаже вищезгадане повідомлення про надсилання на екрані, він викличе метод, який надішле дані форми на сервер: this.sendFormData (). Для простоти я додав setTimeout, щоб імітувати це.

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

У React метод this.setState () надає компонент з новими властивостями. Таким чином, ви також можете додати певну логіку в метод render () компонента форми, який буде вести себе по-різному в залежності від типу відповіді, яку ми отримуємо від сервера. Наприклад:

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

кодоп


1

Якщо у вас є кілька випадків імені елемента, тоді вам доведеться використовувати 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);
};

Зауважте, що в цьому випадку dels - це RadioNodeList, а не масив і не є Iterable. ForEach () - це вбудований метод класу списку. Тут ви не зможете використовувати карту () або зменшити ().


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.