2017-10-16 80 views
0

我爲項目使用了React和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; 

所以,基本上,這取決於列表項被點擊更新我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'上的那個變量。您可以將動態組件存儲在局部變量中。 '讓組件; if(this.state.paymentProviders.providerName ==='stripe'){component = } else if(...){...}'............'

{component}
' – nbkhope

+0

是的,但是如何確保新視圖僅在點擊按鈕時呈現,而不是ListItem點擊? – typos

+0

@typos如何跟蹤你是否使用組件狀態(布爾)屬性單擊它? – nbkhope

1

只需添加一個有條件的渲染方法,檢查狀態,如果條件合適呈現新組件:

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時,你基本上會渲染一個新組件。但是我想要做的是當用戶點擊Pay按鈕時我想呈現一個新組件。爲簡潔起見,我刪除了樣式,但是在我的代碼中發生的情況是,當用戶單擊其中一個ListItem時,單擊的ListItem會更改樣式,因此用戶知道他/她已點擊了哪個樣式,另外我更新了'indexOfClickedItem'。然後,當用戶按下「付款」按鈕時,即我想要呈現新組件時。 – typos

+0

這是相同的概念。 – nbkhope

+0

@nbkhope然後,我不明白它是如何相同的。你能否更新代碼以反映這些變化? – typos