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

У меня есть простая форма в моем 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 поля?

32 ответа

Решение

Использовать 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 для достижения того же результата, но теперь он устарел в пользу установки значения и изменения обработчика (как указано выше):

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

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

1) Получить значения из массива элементов формы по индексу

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

2) Использование атрибута имени в 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>
    )
  }
}

Добавляем к ответу Майкла Шока:

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

Посмотрите эту среднюю статью: Как обрабатывать формы с помощью Just React

Этот метод получает данные формы только при нажатии кнопки "Отправить". Гораздо чище ИМО!

Для тех, кто не хочет использовать ref и сбрасывать состояние с помощью OnChange вы можете просто использовать простой дескриптор OnSubmit и пройти через FormDataобъект. В этом примере используются React Hooks:

const LoginPage = () =>{
    const handleSubmit = (event) => {
        const formData = new FormData(event.target);
        event.preventDefault();
        for (let [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>)
        }

Не нужно использовать ссылки, вы можете получить доступ с помощью события

function handleSubmit(e) {
    e.preventDefault()
    const {username, password } = e.target.elements
    console.log({username: username.value, password: password.value })
}

<form onSubmit={handleSubmit}>
   <input type="text" id="username"/>
   <input type="text" id="password"/>
   <input type="submit" value="Login" />
</form>

Альтернативный подход заключается в использовании 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.

По многим причинам, описанным в разделе Как использовать переключатели в React? этот подход не всегда лучший, но он представляет полезную альтернативу в некоторых простых случаях.

Простой способ справиться с реферами:

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;

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

Если у всех ваших входов / текстовой области есть имя, вы можете отфильтровать все из 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, value, defaultValue...

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

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

}

Вот самый короткий способ получить данные из формы и лучший способ избежать идентификатора и ссылки, просто используя FormData

      import React, { Component } from 'react'

class FormComponent extends Component {
  formSubmit = (event) => {
    event.preventDefault()
    var data = new FormData(event.target)
    let formObject = Object.fromEntries(data.entries())
    console.log(formObject)
  }
  render() {
    return (
      <div>
        <form onSubmit={this.formSubmit}>
          <label>Name</label>
          <input name="name" placeholder="name" />
          <label>Email</label>
          <input type="email" name="email" />
          <input type="submit" />
        </form>
      </div>
    )
  }
}
export default FormComponent

Для пользователей TypeScript

      import react from 'react'

interface FormInterface {
    [key: string]: string
}

const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
   event.preventDefault();
   let formData = new FormData(event.currentTarget)
   let formObj: FormInterface = {}
   for (let [key, value] of Array.from(formData.entries())) {
     formObj[key] = value.toString()
   }
};

<form onSubmit={handleSubmit}>
   <input type="text" name="email" placeholder="Email" />
   <input type="password" name="password" placeholder="Password" />
   <button type="submit">Login</button>
</form>

TypeScript будет жаловаться, если вы попробуете решение Александра Сушкевича . Один обходной путь можно сделать с помощью утверждений типа:

      <form
    onSubmit={(e: React.SyntheticEvent) => {
      e.preventDefault();
      const target = e.target as typeof e.target & {
        username: { value: string };
        password: { value: string };
      };
      const username = target.username.value; // typechecks
      const password = target.password.value; // typechecks
      // etc...
    }}
>
<input type="text" name="username"/>
...

Тем не менее, это всего лишь обходной путь, потому что здесь вы говорите TypeScript, чего ожидать. Это сломается во время выполнения, если вы добавите значение, у которого нет соответствующего элемента ввода.

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

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

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

Я использую так, используя состояние 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})
}`

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

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

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

Во многих событиях в 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>
    );
  }
}

Это пример динамически добавляемого поля. Здесь данные формы будут храниться по ключу имени ввода с использованием хука React useState.

         import React, { useState } from 'react'

function AuthForm({ firebase }) {
    const [formData, setFormData] = useState({});

    // On Form Submit
    const onFormSubmit = (event) => {
        event.preventDefault();
        console.log('data', formData)
        // Submit here
    };

    // get Data
    const getData = (key) => {
        return formData.hasOwnProperty(key) ? formData[key] : '';
    };

    // Set data
    const setData = (key, value) => {
        return setFormData({ ...formData, [key]: value });
    };

    console.log('firebase', firebase)
    return (
        <div className="wpcwv-authPage">
            <form onSubmit={onFormSubmit} className="wpcwv-authForm">
                <input name="name" type="text" className="wpcwv-input" placeholder="Your Name" value={getData('name')} onChange={(e) => setData('name', e.target.value)} />
                <input name="email" type="email" className="wpcwv-input" placeholder="Your Email" value={getData('email')} onChange={(e) => setData('email', e.target.value)} />
                <button type="submit" className="wpcwv-button wpcwv-buttonPrimary">Submit</button>
            </form>
        </div>
    )
}

export default AuthForm

 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>

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

Улучшить пользовательский опыт; когда пользователь нажимает на кнопку отправки, вы можете попытаться получить форму, чтобы сначала показать отправляющее сообщение. Получив ответ от сервера, он может соответствующим образом обновить сообщение. Мы достигаем этого в 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 ( ...

codepen

Это может помочь пользователям 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 );
}

Самое простое решение, которое пришло мне в голову, это:

      <form onSubmit={(e) => handleLogin(e)}>
    <input type="text" name="email" placeholder="Email" />
    <input type="password" name="password" placeholder="Password" />
    <button type="submit">Login</button>
</form>

Функция вашей ручки:

      const handleLogin = (e) => {
    e.preventDefault()
    const data = {
        email: e.target.elements.email.value,
        password: e.target.elements.password.value
    }
    console.log('FormData: ', data)
}

Когда вы нажмете кнопку входа в систему, вы увидите FormData в консоли в следующем формате:FormData: {email: 'whatever you tiped here', password: 'also whatever you tiped here'}.

e.target.elements.email.valueнацелены на элементы с определенным именем, в вашем случае это адрес электронной почты и пароль.

Послеconsole.logвhandleLogin, вы можете выполнить некоторую логику проверки и логику входа.

      const HandleSubmit = (e) => {
    e.preventDefault();
    let formData = e.target[0].form;
        axios({
            url: 'http://localhost:4000/data/add',
            method: 'POST',
            data: new FormData(formData)
        }).then(async (data) => {
            await toastr.success('Added Successfully', {
                timeOut: 1000,
            });
            await setTimeout(() => {
                window.location.reload();
            }, 1000)

        })
    }

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

      <form onSubmit={handleLogin}>
      <input type="text" name="email" placeholder="Email" />
      <input type="text" name="password" placeholder="Password" />
      <button type="submit">Login</button>
</form>

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

Если вы используете React 18, этот подход подойдет вам:

      export default function Search() {
  function search(e) {
        e.preventDefault();
        console.log("search clicked data = " + e.target[0].value);
  }
  return (
    <form onSubmit={search}>
      <input name="query" />
      <button type="submit">Search</button>
    </form>
  );
}

официальная документация не работает, но вот ссылка на случай, если в будущем они это исправят: https://react.dev/reference/react-dom/comComponents/form#handle-form-submission-on-the-client

Думаю, это тоже ответ, который вам нужен. Кроме того, здесь я добавляю обязательные атрибуты. Атрибуты onChange каждого входного компонента являются функциями. Вам нужно добавить туда свою логику.

handleEmailChange: function(e) {
    this.setState({email: e.target.value});
},
handlePasswordChange: function(e) {
   this.setState({password: e.target.value});
},
formSubmit : async function(e) {
    e.preventDefault();
    // Form submit Logic
  },
render : function() {
      return (
        <form onSubmit={(e) => this.formSubmit(e)}>
          <input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleEmailChange} required />
          <input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handlePasswordChange} required />
          <button type="button">Login</button>
        </form>);
},
handleLogin: function() {
    //Login Function
}

Это будет самый простой способ

      const formValidator = (form) => {
    let returnData = {}
    console.log(form.length);

    for (let i = 0; i < form.length; i++) {
        const data = form[i]
        if (data.name != null && data.name != "") {
            returnData[data.name] = data.value;
        }
    }
    return returnData
}

По форме просто

      <form onSubmit={(e) => {
          e.preventDefault()
          let data = formValidator(e.currentTarget)
         }}>
          <RoundTextFiled name='app-id' style={{ marginTop: '10px', borderRadius: '20px' }} label="App id" fullWidth required />
          <RoundTextFiled name='api-hash' style={{ marginTop: '5px' }} label="Api hash" fullWidth required />
          <RoundTextFiled name='channel-id' style={{ marginTop: '5px' }} label="Channel id" fullWidth required />
          <Button type='submit' variant="contained" fullWidth style={{ padding: '10px', marginTop: '5px', borderRadius: '10px' }}>Login</Button>
        </form>
Другие вопросы по тегам