Получить данные формы в Reactjs

121

У меня есть простая форма в моей функции 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?

  • 19
    Точно не относится к React, но ваши формы должны всегда определять action и обрабатываться вашим бэкэндом должным образом. button должна быть type="submit" , и вместо этого обработчик должен быть onsubmit на форму. Используйте формы, разработанные в HTML, и ваши пользователи получат пользу.
  • 8
    @ssorallen Что это за ерунда? Запрашивающий может создавать SPA и, возможно , не хочет, чтобы форма отправлялась как обычная HTML-форма. Если бы они этого хотели, они бы определили действие и удалили обработчик событий.
Показать ещё 2 комментария
Теги:
frontend

16 ответов

123
Лучший ответ

Используйте события 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);
}

Рабочая скрипка: http://jsfiddle.net/kTu3a/

Кроме того, прочитайте документы, есть целый раздел, посвященный обработке формы: http://facebook.github.io/react/docs/forms.html

Раньше вы могли также использовать React для двусторонней настройки привязки databinding helper mixin для достижения того же, но теперь он устарел в пользу установки обработчика значения и изменения (как указано выше):

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

Документация находится здесь: http://facebook.github.io/react/docs/two-way-binding-helpers.html

  • 0
    Каковы преимущества и недостатки использования onchange v / s и mixin?
  • 0
    Я думаю, что это не очень популярен в документах, так как модель потока данных React больше похожа на «одностороннюю привязку данных», и пользователям рекомендуется больше думать об этом. При этом сами документы признают, что ReactLink является чисто синтаксическим сахаром для способа «onChange» / «setState».
Показать ещё 11 комментариев
52

Есть несколько способов сделать это:

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>
    )
  }
}
  • 0
    Это должен быть принятый ответ!
39

Альтернативный подход - использовать атрибут 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-узел
15

Простой способ справиться с refs:

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
  • 0
    Здорово! :) Мне нравится использовать Object.keys() за которым следует map() например: Object.keys(this.refs).map(field => formData[field] = this.refs[field].value)
Показать ещё 4 комментария
9

Я бы предложил следующий подход:

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

}
6

Вы можете переключить обработчик событий 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
}
5

Если у всех ваших входов/текстовой области есть имя, вы можете отфильтровать все из event.target:

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

Полностью неконтролируемая форма form без методов onChange, value, defaultValue...

4

Дайте ваши ссылки, как это

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

тогда вы можете получить к нему доступ в своем дескрипторе, как Су

handleLogin: function(e) {
   e.preventDefault();
    console.log(this.refs.email.value)
    console.log(this.refs.password.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>

Выходное изображение прилагается здесь

  • 0
    Пожалуйста, предоставьте объяснение.
  • 2
    Я постараюсь объяснить это, что я нашел блестящим. В функции handleSubmit () вы создаете объект (formData), в котором ключ является атрибутом 'ref' каждого ввода в форме (оператор 'formData [data]'), а значение является значением ввода с этим атрибутом 'ref' (оператор 'this.refs [data] .value'). С помощью 'formData [data] = this.refs [data] .value' вы создаете этот объект. Вы в буквальном смысле говорите: formData ['username'] = (значение ввода имени пользователя) и formData ['password'] = (значение ввода пароля) Вывод будет: {user: 'blablabla', password: 'xxx }
Показать ещё 1 комментарий
3

Во многих событиях в 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>
    );
  }
}
  • 1
    очень помогло ... спасибо @Alireza
3

Если вы используете Redux в своем проекте, вы можете использовать этот компонент более высокого порядка https://github.com/erikras/redux-form.

2

Кроме того, это также можно использовать.

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);
}
  • 2
    Пожалуйста, включите объяснение, почему этот ответ правильный путь.
  • 1
    Я использую только один метод, чтобы изменить текстовую форму
Показать ещё 1 комментарий
1

Более наглядный пример с разрушением 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>
        );
    }
}
1

Это может помочь пользователям 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) должен быть просто: this.submitForm
  • 0
    Ошибка: компоненты функции без сохранения состояния не могут иметь ссылок.
Показать ещё 1 комментарий
0

Если у вас есть несколько вхождений имени элемента, вы должны использовать 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() является встроенным методом класса списка. Вы не сможете использовать карту() или уменьшить() здесь.

0

Улучшить работу пользователя; когда пользователь нажимает кнопку отправки, вы можете попытаться получить форму, чтобы сначала показать отправленное сообщение. Как только мы получим ответ от сервера, он может соответствующим образом обновить сообщение. Мы достигаем этого в Реактировании, связывая статусы. См. codepen или ниже:

Следующий способ делает первое изменение состояния:

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

codepen

Ещё вопросы

Сообщество Overcoder
Наверх
Меню