2016-03-04 25 views
5

Reactを使い始めたばかりで、子コンポーネント内の入力の入力値を集めるのに問題があります。基本的には、私が作成している大きなフォームのためのさまざまなコンポーネントを作成していますが、包括的なコンポーネントでは、データを呼び出すオブジェクトの子にあるすべての入力値を収集し、その収集した入力をPOST AJAXリクエスト(私が最後に作成したコンポーネントの例を見ることができます)。私は、コンポーネントの内部にあるときに値を簡単に引き出すことができますが、私が理解していない親コンポーネントからそれらを引き出します。Reactの子コンポーネントから値を取得する方法

ありがとうございます。 Reactで今すぐ痛みを経験するだけで、これをどのように構造化するかについての推奨事項は、私はすべての耳です!ここで

は私のコンポーネントは以下のとおりです。

コンポーネント1

var StepOne = React.createClass({ 
    getInitialState: function() { 
    return {title: '', address: '', location: ''}; 
    }, 
    titleChange: function(e) { 
    this.setState({title: e.target.value}); 
    }, 
    addressChange: function(e) { 
    this.setState({address: e.target.value}); 
    }, 
    locationChange: function(e) { 
    this.setState({location: e.target.value}); 
    }, 
    render: function() { 
    return (
     <div className="stepOne"> 
     <ul> 
      <li> 
      <label>Title</label> 
      <input type="text" value={this.state.title} onChange={this.titleChange} /> 
      </li> 
      <li> 
      <label>Address</label> 
      <input type="text" value={this.state.address} onChange={this.addressChange} /> 
      </li> 
      <li> 
      <label>Location</label> 
      <input id="location" type="text" value={this.state.location} onChange={this.locationChange} /> 
      </li> 
     </ul> 
     </div> 
    ); 
    }, // render 
}); // end of component 

コンポーネント2

var StepTwo = React.createClass({ 
    getInitialState: function() { 
    return {name: '', quantity: '', price: ''} 
    }, 
    nameChange: function(e) { 
    this.setState({name: e.target.value}); 
    }, 
    quantityChange: function(e) { 
    this.setState({quantity: e.target.value}); 
    }, 
    priceChange: function(e) { 
    this.setState({price: e.target.value}); 
    }, 
    render: function() { 
    return (
     <div> 
     <div className="name-section"> 
     <div className="add"> 
      <ul> 
      <li> 
       <label>Ticket Name</label> 
       <input id="name" type="text" value={this.state.ticket_name} onChange={this.nameChange} /> 
      </li> 
      <li> 
       <label>Quantity Available</label> 
       <input id="quantity" type="number" value={this.state.quantity} onChange={this.quantityChange} /> 
      </li> 
      <li> 
       <label>Price</label> 
       <input id="price" type="number" value={this.state.price} onChange={this.priceChange} /> 
      </li> 
      </ul> 
     </div> 
     </div> 
     </div> 
    ); 
    } 
}); 

最終的なコンポーネントのデータを収集し、AJAXリクエスト

EventCreation = React.createClass({ 
getInitialState: function(){ 
    return {} 
}, 
submit: function (e){ 
    var self 

    e.preventDefault() 
    self = this 

    var data = { 
    // I want to be able to collect the values into this object then send it in the ajax request. I thought this sort of thing would work below: 
    title: this.state.title, 
    } 

    // Submit form via jQuery/AJAX 
    $.ajax({ 
    type: 'POST', 
    url: '/some/url', 
    data: data 
    }) 
    .done(function(data) { 
    self.clearForm() 
    }) 
    .fail(function(jqXhr) { 
    console.log('failed to register'); 
    }); 
}, 
render: function() { 
    return(
     <form> 
     <StepOne /> 
     <StepTwo /> 
     // submit button here 
     </form> 
    ); 
    } 
}); 

答えて

1

ファーストを提出する、あなた必要一部をreferencesに設定します。 DOM要素を簡単に手に入れることができます。 例:

var data = { 
name: this.refs.stepOneName.value 
} 

EDIT 1: あなたも、あなたのコンポーネントにrefを追加する必要が

<input id="name" type="text" value={this.state.ticket_name} onChange={this.nameChange} ref="stepOneName"/> 

次に、あなたのsubmit方法では、あなただけのようにそれを取り戻すことができます。

レンダリング:function(){ return( //ここにボタンを送信 ); } Anが、その後、あなたの要素へのアクセス:

var data = { 
    name: this.refs.steOneRef.refs.stepOneName.value 
    } 

I JSFiddled your codeアリそれは私のためにOKらしいです。

+0

私はこの前に試してみましたが、データの値を試してみると、常に値が定義されていません。なぜこのようなことが起こるのか? – luke

+0

@luke jsfiddledコードを試すことができますか? – Zakaria

6

子供をレンダリングするときに、必要なデータを返す子コンポーネントのメソッドを定義し、必要なデータを取得するときに後でそのメソッドを呼び出すことができるようにrefsを定義します子供たちに。

StepOne = React.createClass({ 
    getData: function() { 
     return this.state; 
    } 
}); 

StepTwo = React.createClass({ 
    getData: function() { 
     return this.state; 
    } 
}); 

EventCreation = React.createClass({ 
    submit: function() { 
     var data = Object.assign(
      {}, 
      this._stepOne.getData(), 
      this._stepTwo.getData() 
     ); 

     // ... do AJAX 
    }, 

    render: function() { 
     return (
      <StepOne ref={(ref) => this._stepOne = ref} /> 
      <StepTwo ref={(ref) => this._stepTwo = ref} /> 
     ); 
    } 
}); 
3

一般的に言えば、親から子供に小道具として機能を渡したいと思うでしょう。子供のデータが変更されると、その関数はコールバックとして呼び出されます。

これは、親コンポーネントがアプリケーション内のすべての状態を追跡し、子コンポーネントに小道具としての状態スライスを渡すという大きな利点があります。各コンポーネントに内部状態を追跡させるのではなく、 (That's the React approach to data flow。)

あなたのコンポーネントは次のようになります。

var StepOne = React.createClass({ 
    handleOnChange: function(e){ 
    this.props.handleChange(e.target.name, e.target.value); 
    },  
    render: function() { 
    return (
     <div className="stepOne"> 
     <ul> 
      <li> 
      <label>Title</label> 
      <input type="text" name="title" value={this.props.title} onChange={this.handleChange} /> 
      </li> 
      ... 
     </ul> 
     </div> 
    ); 
    }, // render 
}); // end of component 

EventCreation = React.createClass({ 
getInitialState: function(){ 
    return {} 
}, 
handleChange: function(name, value){ 
    var tmp = {}; 
    tmp[name] = value; 
    this.setState(tmp); 
}, 
submit: function (e){ 
    var self 

    e.preventDefault() 
    self = this 

    var data = { 
    // I want to be able to collect the values into this object then send it in the ajax request. I thought this sort of thing would work below: 
    title: this.state.title, 
    } 

    // Submit form via jQuery/AJAX 
    $.ajax({ 
    type: 'POST', 
    url: '/some/url', 
    data: data 
    }) 
    .done(function(data) { 
    self.clearForm() 
    }) 
    .fail(function(jqXhr) { 
    console.log('failed to register'); 
    }); 
}, 
render: function() { 
    return(
     <form> 
     <StepOne handleChange={this.handleChange.bind(this)} title={this.state.title} .../> 
     <StepTwo handleChange={this.handleChange.bind(this)} ... /> 
     // submit button here 
     </form> 
    ); 
    } 
}); 
+1

あなたはそれに私を打つが、私はあなたの考え方を好む;) – Jack

+0

こんにちはajm、助けてくれてありがとう。これは間違いなく私がそれを実装する方法です。 stepOneコンポーネントのhandleOnChange関数を変更しました。スペルミスであったと思います。私の反応コンソールでは、入力中に状態が表示されているのを見ることができますが、入力値に関連するキーはありません。それは 'title = {this.state.title}'は最終的なコンポーネントのStepOneレンダリングの中で何をしているのですか? – luke

+0

'title = {this.state.title}'は 'EventCreation'の状態から' StepOne'を 'prop'として' title'を渡します。 'this.props.title'を介して' StepOne'にアクセスすることができます(あなたの場合、入力の値を設定しているように見えます)。入力されているもののキーを取得しようとしている場合、 'EventCreation'の' handleChange'関数を呼び出す 'StepOne'レベルの関数で渡す必要があります。 – ajm

0

はここでもう少し疎結合ソリューションです。それは、あなたが要素ごとにidを設定することによって決まります。基本的には、データを取得して設定する親コンポーネントのonChange関数を呼び出すことです。

var StepOne = React.createClass({ 
    getInitialState: function() { 
    return {title: '', address: '', location: ''}; 
    }, 
    _onChange(e) { 
    // set your state if needed 

    // call the parent function 
    this.props.onChange(
     e.target.id, 
     e.target.value 
    ) 
    }, 
    render: function() { 
    return (
     <div className="stepOne"> 
     <ul> 
      <li> 
      <label>Title</label> 
      <input id="title" type="text" value={this.state.title} onChange={this._onChange.bind(this)} /> 
      </li> 
      <li> 
      <label>Address</label> 
      <input id="address" type="text" value={this.state.address} onChange={this._onChange.bind(this)} /> 
      </li> 
      <li> 
      <label>Location</label> 
      <input id="location" type="text" value={this.state.location} onChange={this._onChange.bind(this)} /> 
      </li> 
     </ul> 
     </div> 
    ); 
    }, // render 
}); // end of component 

var StepTwo = React.createClass({ 
    getInitialState: function() { 
    return {name: '', quantity: '', price: ''} 
    }, 
    _onChange(e) { 
    // set your state if needed 

    // call the parent function 
    this.props.onChange(
     e.target.id, 
     e.target.value 
    ) 
    }, 
    render: function() { 
    return (
     <div> 
     <div className="name-section"> 
     <div className="add"> 
      <ul> 
      <li> 
       <label>Ticket Name</label> 
       <input id="name" type="text" value={this.state.ticket_name} onChange={this._onChange.bind(this)} /> 
      </li> 
      <li> 
       <label>Quantity Available</label> 
       <input id="quantity" type="number" value={this.state.quantity} onChange={this._onChange.bind(this)} /> 
      </li> 
      <li> 
       <label>Price</label> 
       <input id="price" type="number" value={this.state.price} onChange={this._onChange.bind(this)} /> 
      </li> 
      </ul> 
     </div> 
     </div> 
     </div> 
    ); 
    } 

    EventCreation = React.createClass({ 
    getInitialState: function(){ 
     return {} 
    }, 
    _onChange(id, value) { 
     this.formData[id] = value; 
    }, 
    submit: function (e){ 
     var self 

     e.preventDefault() 
     self = this 

     // Submit form via jQuery/AJAX 
     $.ajax({ 
     type: 'POST', 
     url: '/some/url', 
     data: this.formData 
     }) 
     .done(function(data) { 
     self.clearForm() 
     }) 
     .fail(function(jqXhr) { 
     console.log('failed to register'); 
     }); 
    }, 
    render: function() { 
     return(
     <form> 
      <StepOne onChange={this.onChange.bind(this)}/> 
      <StepTwo onChange={this.onChange.bind(this)}/> 
      // submit button here 
     </form> 
    ); 
    } 
}); 
関連する問題