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() { ... }アクセスEmailPasswordフィールドには何を書けばよいですか?


11
@ssorallenこれはなんてナンセンスなの?質問者はSPAを作成している可能性があり、通常のHTMLフォームのようにフォームを送信したくない場合があります。これが必要な場合は、アクションを定義してイベントハンドラーを削除します。
developerbmw

6
注:onSubmitボタンのクリックではなく、フォームを処理する必要があります-この方法では、Enterキーを押してフォームを送信するユーザーも処理します。
developerbmw

10
A <form><button><input>type=submit、ユーザーを押すが、フォームのいずれかで入力したときに提出されます<input type=text>onClickボタンに依存する場合、ユーザーはボタンをクリックするか、ボタンにフォーカスしてEnter /スペースバーを押す必要があります。を使用onSubmitすると、両方の使用例が有効になります。フォームがEnter to submitをサポートしていない場合、フォームが壊れたように感じることがあります。
ロス・アレン

回答:


166

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
ボタンでonClickの代わりにフォームでonSubmitを使用することもできます
sai

59
フォームの各要素に状態を使用する理由 誰かがこれを悪いパターンだと思っていますか?
eveevans 2016

6
valueLinkは廃止されているようです
Matt Broekhuis

3
これは、クライアント側でパスワードを平文でずっと保存しているのではないですか?これは、パスワードフィールドには適切ではないようです。
NewbiZ 2018

166

これにはいくつかの方法があります。

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

1
これは素晴らしい答えです。これを行うための複数の方法をリストしていただきありがとうございます。
Beau Smith、

オプション2は機能しません。入力の名前が「username」であるにもかかわらず、プロパティ「elements」も「username」もありません
Madacol

@Madacolこれは、同じ名前の入力がいくつかある場合に発生する可能性があります
Aliaksandr Sushkevich '28

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
このソリューションは本当に優れていて、質問時に利用できなかったのですか、それとも「醜い」方法ですか?
Wagner Leonardi

4
実際には、すでにHTMLノードReact.findDOMNode this.refs.theInputを必要としない
ファリードAlnamrouti

23

refを処理する簡単な方法:

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
このメソッドは将来的に廃止される予定です。refは、コールバックでのみ使用され、文字列では使用されません。詳細:facebook.github.io/react/docs/refs-and-the-dom.html
David Labbe

涼しい!:)私はこのようにObject.keys()続けて使用するのがmap()好きです:Object.keys(this.refs).map(field => formData[field] = this.refs[field].value)
フランシス・ロドリゲス

はい、文字列参照は非推奨です。今それを行うためのより良い方法は、onChangeコールバックを使用することです。それでもレフリーを使用したい場合は、このsynctaxを使用することができます:<input type="text" ref={(input) => { this.textInput = input; }} />
E.得意

@ E.Fortes、onChangeコールバックメソッドについて説明してもらえますか?よろしくお願いします。私にタグを付けてください。そうすればあなたの答えがわかります。
Simona Adriani、2018

簡単な方法は次のとおりです(コードフォーマッタが機能していないことをお詫びします)。this.state = {値: ''}; 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.フォルテス2018

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

この中級の記事を参照してください。

このメソッドは、[送信]ボタンが押されたときにのみフォームデータを取得します。ずっときれいなIMO!


完璧な答え。👌
ミハル

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(user);'を実行する 使用可能な値のないオブジェクトを与えます!意見はありますか?
M

@MahdiRafatjah¯\ _(ツ)_ / ¯-
Michael Schock

私の友人は、文書を反応させるために私を呼ばれ、彼らはこのようにそれをやっているreactjs.org/docs/forms.html#controlled-components
のM

1
いいですね、
Michael Schock

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。destination}"。また、フォームを再レンダリングしないと、フォームでリアクション検証を実行できません
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,
      }), {})
}

完全に制御されていないフォームon onChangeメソッド、値、defaultValueなし...


12

refを使用せず、OnChangeイベントで状態をリセットしたくない場合は、単純なOnSubmitハンドルを使用して、FormDataオブジェクトをループ処理できます。この例では、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>)
        }

すばらしい答えですが、ちょっとしたピックでvarを削除できます。
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
この回答が正しい方法である理由を説明してください。
Tim Hutchison

1
テキストの形式を変更する方法は1つだけです
Yurii Kosygin '27 / 07/17

パスワードは、react devツールで確認できますが、セキュリティ上の問題がありますか?
Neil、

5

このような参照を入力に与える

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

その後、あなたはあなたのhandleLoginで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

JavaScriptの多くのイベントでは、eventどのイベントが発生したか、何が値であるかなどを含むオブジェクトを提供しています。

これは、ReactJのフォームでも使用しています...

したがって、コードで状態を新しい値に設定します...次のようなもの:

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()関数では、キーがフォーム内のすべての入力の「ref」属性(「formData [data]」ステートメント)であり、値が入力の値であるオブジェクト(formData)を構築していますこの「ref」属性(「this.refs [data] .value」ステートメント)。'formData [data] = this.refs [data] .value'を使用して、このオブジェクトを構築しています。文字通り、formData ['username'] =(ユーザー名入力の値)およびformData ['password'] =(パスワード入力の値)出力は次のようになります:{user: 'blablabla'、password: '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)は次のようにする必要があります:this.submitForm
rekarnar

エラー:ステートレス関数コンポーネントは参照を持つことができません。
ホルムズ2017年

Meteor(v1.3)を使用していますか?
ジョーL.

1

ユーザーエクスペリエンスを向上させるため。ユーザーが送信ボタンをクリックしたときに、最初に送信メッセージを表示するフォームを取得することができます。サーバーからの応答を受信すると、それに応じてメッセージを更新できます。ステータスをチェーンすることで、Reactでこれを実現します。以下のコードペンまたはスニペットを参照してください:

次のメソッドは、最初の状態を変更します。

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

Reactが上記のSendingメッセージを画面に表示するとすぐに、フォームデータをサーバーに送信するメソッド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()は、リストクラスの組み込みメソッドです。ここではmap()またはreduce()を使用できません。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.