2017-10-16 12 views
0

私はプロジェクトにReact and Material UIを使用しています。支払い方法を実装しています。私は基本的に、さまざまなタイプの支払い方法をサポートし、どのユーザーがどちらを選択するかに応じてフォームを表示したいと思います。ユーザーがフォームを入力して送信すると、前のビューに戻ります。Reactでボタンをクリックしてコンポーネントをレンダリングする方法は?

import React, { Component } from 'react'; 
import { List, ListItem } from 'material-ui'; 
import { Button } from '../../components'; 
import StripeForm from './stripe/form'; 
import PropTypes from 'prop-types'; 

class MyComp extends Component { 
    constructor(props) { 
     super(props); 

     this.state = { 
      paymentProviders: [], 
      indexOfClickedItem: -1, 
     }; 

     this.onListItemClicked = this.onListItemClicked.bind(this); 
     this.onPayment = this.onPayment.bind(this); 
    } 

    onListItemClicked(paymentProvider, index) { 
     let paymentProviders = { 
      providerName: paymentProvider.ProviderName, 
      publicKey: paymentProvider.PublicKey, 
     }; 
     this.setState({ 
      paymentProviders: paymentProviders, 
      indexOfClickedItem: index, 
     }); 
    } 

    onPayment() { 
     switch (this.state.paymentProviders.providerName) { 
      case "stripe": 
       // render the form for stripe payment 
       return (<StripeForm />); 

      case "paypal": 
       // render the form for paypal payment 

      default: 
       return null; 
     } 
    } 

    render() { 
     return (
      <div> 
       <div> 
        <List> 
         {this.props.paymentProviders.map((pp, index) => { 
          return (
           <ListItem key={pp.ProviderName} 
             primaryText={pp.ProviderName} 
             onClick={() => this.onListItemClicked(pp, index)} 
           /> 
          ) 
         })} 
        </List> 
       </div> 

       <div> 
        <Button onClick={this.onPayment} 
          label="Pay" /> 
       </div> 
      </div> 
     ); 
    } 
} 

MyComp.propTypes = { 
    paymentProviders: PropTypes.array.isRequired, 
}; 

export default MyComp; 

ので、基本的には、その上のListItemは、私は私のindexOfClickedItem状態に更新クリックすると依存し、その後も、支払プロバイダに関するいくつかの詳細をアップデート:私はこのようになりますコンポーネントを持っています。しかし、私が主に成し遂げたいのは、自分のボタンがクリックされたときに、どの支払プロバイダが選択されたか(以前にクリック/選択されたリストを意味する)に応じて、別のコンポーネントをレンダリングすることです。どのようにそれを達成するためのアイデア?

+0

[React Router](https://reacttraining.com/react-router/web/guides/philosophy)、特に 'Switch'を使用することができます – Dane

+0

オプションがあるので、インライン条件付きレンダリングを使用して非表示にすることもできますコンポーネントはコンポーネントの状態に基づいています。 – fungusanthrax

+0

@fungusanthraxコードサンプルは非常に歓迎されています。 – typos

答えて

1

条件付きレンダリングを使用できます。

まず、フォームを保存するために、コンストラクタ内の変数を初期化し、フォームを表示するかどうかを管理するための状態viewFormを追加します。ボタンクリックで

constructor(props) { 
    super(props); 

    this.state = { 
     paymentProviders: [], 
     indexOfClickedItem: -1, 
     viewForm: false 
    }; 

    this.onListItemClicked = this.onListItemClicked.bind(this); 
    this.onPayment = this.onPayment.bind(this); 
    this.paymentForm = null; //this 
} 

、とき支払条件付きでそれに値を割り当てますモードが選択され、およびフォームを表示した状態に変化している..

switch (this.state.paymentProviders.providerName) { 
     case "stripe": 
      this.paymentForm = <StripeForm/> 
      break; 
     case "paypal": 
      this.paymentForm = <PaypalForm/> 
      break; 
     default: 
       this.paymentForm = null; 
    } 
    this.setState({ viewForm: true }); 

をして、条件付きでそれをレンダリング:

<div className='form-container'> 
    {(this.state.viewForm) ? 
    this.paymentForm : ''} 
</div> 
+0

この変数は 'this'には必要ありません。動的コンポーネントをローカル変数に格納するだけで済みます。 'letコンポーネント。 if(this.state.paymentProviders.providerName === 'stripe'){component = } else if(...){...} '............'

{component}
' – nbkhope

+0

はい、ただし、新しいビューはボタンクリックでのみ表示され、ListItemでは表示されないようにするにはどうすればよいですか? – typos

+0

@typosコンポーネント状態(ブール値)プロパティを使用してそれをクリックしたかどうかを追跡する方法はありますか? – nbkhope

1

だけの状態を調べ、条件が正しい場合は、新しいコンポーネントを描画するあなたのrenderメソッドに条件を追加します。

render() { 
    // render payment provider component for selected provider 
    const {paymentProviders, indexOfClickedItem, paymentClicked} = this.state; 
    const selectedPP = paymentProviders && paymentProviders[indexOfClickedItem]; 
    if (paymentClicked) { 
     // whatever mechanism you want to use to decide 
     // what to render for this payment provider... 
     const ComponentToRender = selectedPP.Component; 
     return (
      <ComponentToRender 
      // unselects the item when the user finishes the payment 
      onComplete={() => this.setState({indexOfClickedItem: -1})} 
      prop1={"foo"} 
      /> 
     ); 
    } 

    // if nothing selected, render list 
    return (
     <div> 
      <div> 
       <List> 
        {this.props.paymentProviders.map((pp, index) => { 
         return (
          <ListItem key={pp.ProviderName} 
            primaryText={pp.ProviderName} 
            onClick={() => this.onListItemClicked(pp, index)} 
          /> 
         ) 
        })} 
       </List> 
      </div> 

      <div> 
       <Button onClick={this.onPayment} 
         label="Pay" /> 
      </div> 
     </div> 
    ); 
} 

あなたonPayment関数は、新しいレンダリングパスをトリガーするthis.setState({paymentClicked: true})を発行する必要があります。

+0

これは私が望むものとは少し異なります。あなたのコードでは、ユーザーがListItemの1つをクリックするたびに、基本的に新しいコンポーネントをレンダリングします。しかし、私がしたいのは、ユーザーが有料ボタンをクリックするたびに新しいコンポーネントをレンダリングしたいということです。簡潔さのためにスタイルを削除しましたが、私のコードでは、ユーザーがListItemの1つをクリックすると、クリックされたListItemがスタイルを変更するので、ユーザーはクリックしたことを認識し、さらに、 'indexOfClickedItem'です。ユーザーが有料ボタンを押すと、その時点で新しいコンポーネントがレンダリングされます。 – typos

+0

同じ概念です。 – nbkhope

+0

@nbkhopeそれで、私はそれがどのように同じか分かりません。変更を反映するためにコードを更新してください。 – typos

関連する問題