ReactJSを使用して入力フィールドの値を取得するにはどうすればよいですか?


189

次のReactコンポーネントがあります。

export default class MyComponent extends React.Component {

    onSubmit(e) {
        e.preventDefault();
        var title = this.title;
        console.log(title);
    }

    render(){
        return (
            ...
            <form className="form-horizontal">
                ...
                <input type="text" className="form-control" ref={(c) => this.title = c} name="title" />
                ...
            </form>
            ...
            <button type="button" onClick={this.onSubmit} className="btn">Save</button>
            ...
        );
    }

};

コンソールは私に与えていますundefined-このコードの何が問題になっていますか?


7
this.onSubmit.bind(this);
zerkms

いいですね
JoeTidee

2
何についてのe.target.valueバインドなし?
omarjmh 2016

1
e.target.valueは、入力フィールドではなくボタンをターゲットにしていませんか?
JoeTidee

onSubmitクリックしたとき(つまりonClick={this.onSubmit.bind(this)})、メソッドを送信ボタン(DOM要素)にバインドする必要があります。また、フォームのタイトル入力の値にアクセスする場合は、を使用できますonSubmit(event) { const title = event.target.elements.title.value; }
tfmontague 2017

回答:


10

MyComponentクラスのReact.Componentの下でコンストラクターを使用する必要があります。

constructor(props){
    super(props);
    this.onSubmit = this.onSubmit.bind(this);
  }

次に、タイトルの結果を取得します


316

ここで3つの答えがあります。使用する(強制される)Reactのバージョン、およびフックを使用するかどうかによって異なります。

まず最初に:

Reactがどのように機能するかを理解することは重要です。それで、物事を適切に実行できるようになります(ヒント:React WebサイトのReactチュートリアル演習を実行するのは非常に価値があります。物)。ここで「適切に」とは、ブラウザーでレンダリングされるアプリケーションインターフェイスを作成していることを意味します。すべてのインターフェース作業は、「Webページを作成している場合に慣れている」ではなく、Reactで行われます(これが、Reactアプリが「Webページ」ではなく「アプリ」である理由です)。

Reactアプリケーションは、次の2つに基づいてレンダリングされます。

  1. 親がそのコンポーネントのインスタンスを作成したときに宣言されたコンポーネントのプロパティ。親はそのライフサイクルを通じて変更できます。
  2. コンポーネント自体の内部状態。コンポーネント自体のライフサイクルを通じてそれ自体を変更できます。

あなたが明示しているではない、あなたが反応を使用するときにすることは、HTML要素を生成し、それらを使用している:あなたが言う使用に反応する場合<input>、例えば、あなたがされていない、あなたが言っている、HTMLの入力要素を作成リアクト入力オブジェクトを作成するために反応これは、たまたまHTML入力要素としてレンダリングされ、そのイベント処理はHTML要素の入力イベントを監視します制御されません

Reactを使用する場合、実行していることは、ユーザーの操作によってコンポーネントの状態を変更する(多くの場合、操作可能な)データをユーザーに提示するアプリケーションUI要素を生成することです。これにより、アプリケーションインターフェイスの一部の再レンダリングが新しい状態を反映する場合があります。このモデルでは、状態は常に最終的な権限であり、「それをレンダリングするために使用されるUIライブラリー」ではなく、WebではブラウザーのDOMです。DOMは、このプログラミングモデルでほぼ後付けです。Reactがたまたま使用しているのは、特定のUIフレームワークだけです。

したがって、入力要素の場合、ロジックは次のとおりです。

  1. 入力要素を入力し、
  2. 入力要素にはまだ何も起こりません。イベントはReactによってインターセプトされ、すぐに終了します
  3. Reactは、イベント処理用に設定した関数にイベントを転送します。
  4. その関数状態の更新をスケジュールするかもしれません
  5. そうである場合、Reactはその状態更新を(非同期で!)実行しrender、更新後に呼び出しをトリガーしますが、状態更新状態を変更し場合のみです
  6. このレンダリングが行われた後にのみ、UIは「文字を入力した」ことを示します。

これらはすべて、ミリ秒単位で発生します。つまり、「ページで入力要素を使用するだけ」と同じ方法で入力要素に入力したように見えますが、それはまったく同じではありません。起こりました。

それで、それで、Reactの要素から値を取得する方法について:

ES5を使用したReact 15以下

物事を適切に行うために、コンポーネントには状態値があり、それは入力フィールドを介して表示されます。UI要素に変更イベントをコンポーネントに送り返させることで、状態値を更新できます。

var Component = React.createClass({
  getInitialState: function() {
    return {
      inputValue: ''
    };
  },

  render: function() {
    return (
      //...
      <input value={this.state.inputValue} onChange={this.updateInputValue}/>
      //...
    );
  },

  updateInputValue: function(evt) {
    this.setState({
      inputValue: evt.target.value
    });
  }
});

したがって、ReactにupdateInputValue関数を使用してユーザーインタラクションを処理しsetState、状態の更新をスケジュールするために使用するように指示します。renderタップを使用this.state.inputValueするという事実は、状態の更新後にレンダリングすると、ユーザーは入力した内容に基づいて更新テキストが表示されることを意味します。

コメントに基づく補遺

UI入力が状態値を表す場合(ユーザーがタブを途中で閉じたときに何が起こるかを考えて、タブが復元されます。入力した値をすべて復元する必要がありますか?そうであれば、それが状態です)。そのため、大きなフォームには数十または数百の入力フォームが必要であるように感じるかもしれませんが、ReactはUIを保守可能な方法でモデル化することです。100の独立した入力フィールドがなく、関連する入力のグループがあるため、それぞれをキャプチャしますコンポーネントでグループ化し、「マスター」フォームをグループのコレクションとして作成します。

MyForm:
  render:
    <PersonalData/>
    <AppPreferences/>
    <ThirdParty/>
     ...

これは、巨大な単一フォームコンポーネントよりもはるかに保守が簡単です。状態を維持してグループをコンポーネントに分割します。各コンポーネントは一度にいくつかの入力フィールドの追跡のみを担当します。

また、すべてのコードを書き出すのは「面倒」だと感じるかもしれませんが、それは誤った節約です。将来のあなたも含めて、あなたではない開発者は、明示的に接続されたすべての入力を確認することで、実際に大きなメリットを得ます。コードパスをトレースしやすくなります。ただし、いつでも最適化できます。たとえば、状態リンカーを作成できます

MyComponent = React.createClass({
  getInitialState() {
    return {
      firstName: this.props.firstName || "",
      lastName: this.props.lastName || "" 
      ...: ...
      ...
    }
  },
  componentWillMount() {
    Object.keys(this.state).forEach(n => {
      let fn = n + 'Changed';
      this[fn] = evt => {
        let update = {};
        update[n] = evt.target.value;
        this.setState(update);
      });
    });
  },
  render: function() {
    return Object.keys(this.state).map(n => {
      <input
        key={n} 
        type="text"
        value={this.state[n]}
        onChange={this[n + 'Changed']}/>
    });
  }
});

もちろん、これには改善されたバージョンがあるので、https://npmjs.comにアクセスして、最も気に入っているReact状態リンクソリューションを検索してください。オープンソースは主に、他の人がすでに行ったことを見つけ、自分ですべてを最初から作成する代わりにそれを使用することです。

React 16(および15.5トランジショナル)および「モダン」JS

React 16(および15.5からソフトスタート)以降、createClass呼び出しはサポートされなくなり、クラス構文を使用する必要があります。これは2つのことを変更します。明らかなクラス構文だけでなく、「無料」で実行できるthisコンテキストバインディングも変更さcreateClassれるため、引き続きthis機能するonWhateverように、ハンドラーで匿名関数を保持するコンテキストに「太い矢印」表記を使用していることを確認してください。onChange私たちはここにコードで使用します。

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      inputValue: ''
    };
  }

  render() {
    return (
      //...
      <input value={this.state.inputValue} onChange={evt => this.updateInputValue(evt)}/>
      //...
    );
  },

  updateInputValue(evt) {
    this.setState({
      inputValue: evt.target.value
    });
  }
});

またbind、次のように、すべてのイベント処理関数のコンストラクターで使用するのを見たことがあるかもしれません。

constructor(props) {
  super(props);
  this.handler = this.handler.bind(this);
  ...
}

render() {
  return (
    ...
    <element onclick={this.handler}/>
    ...
  );
}

それをしないでください。

を使用しているほとんどの場合bind、「あなたはそれを間違っている」ということわざが当てはまります。クラスはすでにオブジェクトプロトタイプを定義しているため、インスタンスコンテキストもすでに定義しています。bindその上に置かないでください。コンストラクターですべての関数呼び出しを複製するのではなく、通常のイベント転送を使用します。これは、その複製によりバグの表面が増加し、コードを呼び出す場所ではなく、コンストラクターに問題がある可能性があるため、エラーの追跡が非常に困難になるためです。また、作業する(持っている、または選択している)他の人にメンテナンスの負担をかけること。

はい、反応ドキュメントはそれが問題ないと言っていることを知っています。そうではありません、それをしないでください。

React 16.8、フックで関数コンポーネントを使用する

React 16.8以降ではpropsフックを使用して、関数コンポーネント(つまり、文字通り引数を取る関数を、コンポーネントクラスのインスタンスであるかのように使用できます。クラスを作成する必要はありません)にも状態を指定できます。

完全なクラスコードが必要なく、単一のインスタンス関数が必要な場合は、useStateフックを使用して単一の状態変数とその更新関数を取得できます。これは、上記の例とほぼ同じように機能しますが、setState関数呼び出し:

import { useState } from 'react';

function myFunctionalComponentFunction() {
  const [input, setInput] = useState(''); // '' is the initial state value
  return (
    <div>
    <label>Please specify:</label>
    <input value={input} onInput={e => setInput(e.target.value)}/>
    </div>
  );
}

以前は、クラスと関数コンポーネントの非公式な区別は「関数コンポーネントには状態がない」でしたので、その背後に隠れることはできません。関数コンポーネントとクラスコンポーネントの違いは、非常によく見られるいくつかのページにあります。 -記述された反応のドキュメント(便利な誤解を招くような簡単な説明はありません)。これを読んで、自分が何をしているのかを理解し、自分でプログラミングするための最善の(それが何であれ)ソリューションを選んだかどうかを知ることができます。あなたが抱えている問題から。


4
あまりにも多くの状態を使用することは悪い考えであると言ういくつかのオンライン記事を読みました。私のアプリケーションの特定のフォームには、約100のフォームフィールドがあります。状態を保存する関数を定義することは、物事を行うための不必要に困難な方法のように感じられます。onClick = {this.onSubmit.bind(this)}を使用できる場合、これは値を取得するための良い方法のようです(必要に応じて、コンポーネントの状態を設定します)。これについてのコメントをいただければ幸いです。
JoeTidee

5
スマートなコードを書いてください。フォーム入力は間違いなく状態です(ユーザーがタブを途中で閉じ、タブが復元された場合にどうなるかを検討してください。入力された値をすべて復元する必要がありますか?はい?それは状態です)。Facebookにも数百のフォーム値があり、狂気への解決策はReactでした。それは本当にうまくいきます。状態を使用しながらコードを少し簡単にする1つの方法は、Reactサイトで説明されているように、双方向の状態リンクを使用することです。読む価値があります!=)
マイク 'Pomax'カマーマンズ2016

2
また、「100フィールド」はほとんど関係がないことに注意してください。フォームを分割すると、100要素ではなく、いくつかのセクションになり、それぞれに入力数があります。適切なデザインを適用し、各セクションを独自のコンポーネントにして、フォームのコンポーネントをグループ化します。グループ。これは通常、コンポーネントが10未満の入力を処理するようになり、突然、情報アーキテクチャーがより意味を持つようになります。フォーム送信は、ブラウザのアクションとして、もちろん「あなたのフォーム」を見て、すべてを一度に送信します。クリーンでターゲットを絞ったUIデザイン。
マイク 'Pomax'カマーマンズ

2
コメントありがとうございます。しかし、React v15の時点で状態リンクが廃止されていることに気付きました。
JoeTidee

3
@JasonChingでは、潜在的なバグをコードに組み込んだだけです。ReactはWebページの「すべてで終わり」のソリューションではなく、インターフェースを構築するためのフレームワークであり、後から考えられるように状態管理と実際のUIレンダリングを担当します(ユーザーはDOMと対話せず、対話します)反応:DOMの更新は、UIが状態を視覚的に反映するように、非同期(ただし非常に高速)の最後のステップです。それをバイパスしたい場合、より重要な質問は次のとおりです。なぜReactを使用しているのですか?あなたがそれを間違って使用している最良のサインはReactとjQueryを組み合わせることです。
Mike 'Pomax' Kamermans

17

次のようなことを実行して、入力フィールドの値を取得できました。

import React, { Component } from 'react';

class App extends Component {

constructor(props){
super(props);

this.state = {
  username : ''
}

this.updateInput = this.updateInput.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}


updateInput(event){
this.setState({username : event.target.value})
}


handleSubmit(){
console.log('Your input value is: ' + this.state.username)
//Send state to the server code
}



render(){
return (
    <div>
    <input type="text" onChange={this.updateInput}></input>
    <input type="submit" onClick={this.handleSubmit} ></input>
    </div>
  );
}
} 

//output
//Your input value is: x

1
「setState」を使用する理由 これには、再レンダリングが含まれます。
Luca Davanzo

15

反応16では、私は使用します

<Input id="number" 
       type="time" 
       onChange={(evt) => { console.log(evt.target.value); }} />

年齢の読み込み時にフィールドが自動的に入力された場合、機能しません
SeanMC '10

4

「this」を関数updateInputValue(evt)にバインドしてこれを行うことに成功しました

this.updateInputValue = this.updateInputValue.bind(this);

ただし、入力値= {this.state.inputValue} ...は良い考えではないことがわかりました。

以下は、babel ES6の完全なコードです。

class InputField extends React.Component{


  constructor(props){
   super(props);
   //this.state={inputfield: "no value"};   
   this.handleClick = this.handleClick.bind(this);
   this.updateInputValue = this.updateInputValue.bind(this);
  }

  handleClick(){
   console.log("trying to add picture url");
   console.log("value of input field : "+this.state.inputfield);

  }

  updateInputValue(evt){
    //console.log("input field updated with "+evt.target.value);
    this.state={inputfield: evt.target.value};   

  }

  render(){
    var r; 
    r=<div><input type="text" id="addpixinputfield" 
            onChange={this.updateInputValue} />
      <input type="button" value="add" id="addpix" onClick={this.handleClick}/>
      </div>;    
    return r;
   }
}

2

あなたのエラーはあなたがクラスを使用しているためであり、クラスを使用するときはうまく機能させるためにこれに関数をバインドする必要があります。とにかく、「これ」と「これ」がJavaScriptで何をする必要があるかについてのチュートリアルはたくさんあります。

送信ボタンを修正すると、うまくいくはずです。

<button type="button" onClick={this.onSubmit.bind(this)} className="btn">Save</button>

また、コンソールにその入力の値を表示する場合は、var title = this.title.value;を使用する必要があります。


2
あなたは「この」についての詳細を知りたい場合は、このリンクは役に立つかもしれません
Soroush Bkの


2

<input>一意のIDを与える

<input id='title' ...>

標準のWeb APIを使用してDOMで参照します

const title = document.getElementById('title').value

キーを押すたびにReact状態を継続的に更新する必要はありません。必要なときに値を取得するだけです。


1
// On the state
constructor() {
  this.state = {
   email: ''
 }
}

// Input view ( always check if property is available in state {this.state.email ? this.state.email : ''}

<Input 
  value={this.state.email ? this.state.email : ''} 
  onChange={event => this.setState({ email: event.target.value)}
  type="text" 
  name="emailAddress" 
  placeholder="johdoe@somewhere.com" />

あなたの答えは質問には良いかもしれませんが、常にいくつかの説明を追加することをお勧めします。追加には2分ほどかかります。これにより、将来のユーザーの回答も改善されます。
DaFois

確かにそうします。
キダリケビン

0

'onChange'関数を追加せずに入力値を取得できます。

入力要素に 'ref attr:を追加するだけです。

そして、必要なときにthis.refsを使用して入力値を取得します。


3
これはもう推奨されません。
JoeTidee 2017

1
それらを使用できますが、プロップとコールバックを使用してデータフローを一方向に保つことをお勧めします。
JoeTidee 2017

参照を正しく追加する例、つまりレガシー文字列の代わりに参照コールバックを使用する例を追加するとよいでしょう。
JoeTidee 2017

0

あなたの参照を変更しますref='title'し、削除name='title' [削除var title = this.titleと書き込み:

console.log(this.refs.title.value)

また、追加.bind(this)する必要がありますthis.onSubmit

(それは私のケースではかなり似ていましたが、onClick私が持っていたのではなくonSubmit={...}、フォーム(<form onSubmit={...} ></form>))に入れられました


0

クラスコンポーネントを使用する場合、3つのステップのみ-最初に、たとえばthis.state = {name: ''}のように入力フィールドの状態を宣言する必要があります。次に、setName()の例のように、状態が変化したときに状態を設定するための関数を記述する必要があります。最後に、たとえば入力jsxを記述する必要があります <input value = {this.name} onChange = {this.setName} />

import React, { Component } from 'react'

export class InputComponents extends Component {
    constructor(props) {
        super(props)

        this.state = {
             name:'',
             agree:false
        }
        this.setName = this.setName.bind(this);
        this.setAgree=this.setAgree.bind(this);
    }

    setName(e){
        e.preventDefault();
        console.log(e.target.value);
        this.setState({
            name:e.target.value
        })
    }
    setAgree(){
        this.setState({
            agree: !this.state.agree
        }, function (){
            console.log(this.state.agree);
        })
    }
    render() {
        return (
            <div>
                <input type="checkbox" checked={this.state.agree} onChange={this.setAgree}></input>
                < input value={this.state.name} onChange = {this.setName}/>
            </div>
        )
    }
}

export default InputComponents

0
export default class MyComponent extends React.Component {

onSubmit(e) {
    e.preventDefault();
    var title = this.title.value; //added .value
    console.log(title);
}

render(){
    return (
        ...
        <form className="form-horizontal">
            ...
            <input type="text" className="form-control" ref={input => this.title = input} name="title" />
            ...
        </form>
        ...
        <button type="button" onClick={this.onSubmit} className="btn">Save</button>
        ...
    );
}

};

0

非制御フィールドを使用する:

export default class MyComponent extends React.Component {

    onSubmit(e) {
        e.preventDefault();
        console.log(e.target.neededField.value);
    }

    render(){
        return (
            ...
            <form onSubmit={this.onSubmit} className="form-horizontal">
                ...
                <input type="text" name="neededField" className="form-control" ref={(c) => this.title = c} name="title" />
                ...
            </form>
            ...
            <button type="button" className="btn">Save</button>
            ...
        );
    }

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