2016-04-11 8 views
0

Ich habe eine Arbeits App mit Ruby on Rails und ReactJS die vier Komponenten:aktualisieren zwei Komponenten keine Beziehung Ruby on Rails & ReactJS

  1. ProductContainer
  2. ProductItem (Kind von ProductContainer)
  3. BasketContainer
  4. BasketItem (Kind BasketContainer)

im Moment ist Ajax neuer Warenkorb Artikel erstellen verwenden ruft wh de Klicken Sie in der Produktartikel-Komponente auf die Schaltfläche "In den Warenkorb". Das funktioniert einwandfrei, aber der Status wird nicht aktualisiert, ohne dass die Seite aktualisiert wurde. Ich bin mir nicht sicher, wie ich BasketContainer/BasketItem darauf hinweisen soll, dass die Komponente erneut gerendert werden muss.

Ich glaube, ich muss SetState auf den Erfolg meiner Ajax-Anruf, aber bin mir nicht sicher, wie dies für eine andere Komponente zu tun. Jeder Rat würde sehr geschätzt werden.

ProductItem Component

class ProductItem extends React.Component{ 

constructor() { 
    super() 

    this.state = { 
     name: '', 
     price: 0, 
     code: '', 
     id: '' 
    } 
} 

componentWillMount() { 
    this.setState({ 
     name: this.props.data.name, 
     price: this.props.data.price, 
     code: this.props.data.code, 
     id: this.props.data.id 
    }) 
} 

addtoBasket() { 
    $.ajax({ 
     type: "POST", 
     url: "/items", 
     dataType: "json", 
     data: { 
      item: { 
       name: this.state.name, 
       price: this.state.price, 
       code: this.state.code 
      } 
     }, 
     success: function() { 
      console.log("success"); 
     }, 
     error: function() { 
      console.log("error"); 
     } 
    }) 
} 

render(){ 
    let productName = this.props.data.name 
    let productPrice = this.props.data.price 
    let productCode = this.props.data.code 
    let productImg = this.props.data.image_url 

    return (
     <div className="col-xs-12 col-sm-4 product"> 
      <img src={productImg}/> 
      <h3 className="text-center">{productName}</h3> 
      <h5 className="text-center">£{productPrice}</h5> 
      <div className="text-center"> 
       <button onClick={this.addtoBasket.bind(this)} className="btn btn-primary">Add to Basket</button> 
      </div> 
     </div> 
    ) 
} 

}

BasketItem Component

class BasketItem extends React.Component{ 

constructor(props) { 
    super() 

    this.state = { 
     name: '', 
     price: 0, 
     code: '', 
     id: '', 
     quantity: 1, 
    } 
} 

componentWillMount() { 
    this.setState({ 
     name: this.props.data.name, 
     price: this.props.data.price, 
     code: this.props.data.code, 
     id: this.props.data.id, 
    }) 
} 

deleteItem() { 
    let finalUrl = '/items/' + this.state.id; 
    $.ajax({ 
     type: "DELETE", 
     url: finalUrl, 
     dataType: "json", 
     success: function(response) { 
      console.log("successfully deleted"); 
     }, 
     error: function() { 
      console.log("error"); 
     } 
    }) 
} 


render(){ 
    let itemName = this.props.data.name 
    let itemCode = this.props.data.code 
    let itemQuantity = 1 
    let itemPrice = (this.props.data.price * itemQuantity).toFixed(2) 
    const itemId = this.props.data.id 

    return(
     <tr> 
      <td>{itemName}</td> 
      <td>{itemCode}</td> 
      <td>{itemQuantity}</td> 
      <td><button className="btn btn-warning" onClick={this.deleteItem.bind(this)}>Remove</button></td> 
      <td>£{itemPrice}</td> 
     </tr> 
    ) 
} 

}

Pr oductContainer Komponente

class ProductContainer extends React.Component { 

constructor() { 
    super() 
    this.state = { 
     products: [] 
    } 
} 

componentWillMount() { 
    this.setState({ 
     products: this.props.products 
    }) 
} 

render(){ 
    let p = this.state.products 

    return(
     <div> 
      <h1>Products</h1> 
      <div className="row"> 
       {p.map(function(product){ 
        return <ProductItem data={product} key={product.id} />; 
       })} 
      </div> 
     </div> 
    ) 
} 

}

BasketContainer Komponente

class BasketContainer extends React.Component{ 

constructor() { 
    super() 
    this.state = { 
     items: [], 
     subTotal: 0, 
     totalPrice: 0, 
     deliveryPrice: 0 
    } 
} 

componentWillMount() { 
    this.setState({ 
     items: this.props.items, 
    }) 
} 

componentDidMount() { 
    this.calculateTotals(); 
} 

calculateTotals() { 
    let subtotal = this.state.subTotal 
    let delivery = this.state.deliveryPrice 

    for (var i=0; i<this.state.items.length; i++) { 
     subtotal += Number(this.state.items[i].price); 
    } 

    if (subtotal > 90) { 
     delivery = 0; 
    } else if (subtotal >= 50 & subtotal < 90) { 
     delivery = 2.95; 
    } else { 
     delivery = 4.95; 
    } 

    this.setState({ 
     deliveryPrice: delivery, 
     subTotal: subtotal, 
     totalPrice: subtotal + delivery 
    }) 
} 

render(){ 

    const { 
     totalPrice, 
     subTotal, 
     deliveryPrice 
    } = this.state; 

    let i = this.state.items 
    let basketBlock; 
    let basketCount; 
    let basketSubtotal; 
    let basketDelivery; 
    let basketTotal; 

    if (i) { 

     if (i.length === 1) { 
      basketCount = (
       <span className="basket-count"> 
        ({i.length} item) 
       </span> 
      ) 
     } else { 
      basketCount = (
       <span className="basket-count"> 
        ({i.length} items) 
       </span> 
      ) 
     } 

     basketSubtotal = (
      <tr> 
       <td></td> 
       <td></td> 
       <td></td> 
       <th>Subtotal</th> 
       <td>£{subTotal.toFixed(2)}</td> 
      </tr> 
     ) 
     basketDelivery = (
      <tr> 
       <td></td> 
       <td></td> 
       <td></td> 
       <th>Delivery</th> 
       <td>£{deliveryPrice.toFixed(2)}</td> 
      </tr> 
     ) 
     basketTotal = (
      <tr> 
       <td></td> 
       <td></td> 
       <td></td> 
       <th>Total</th> 
       <td>£{totalPrice.toFixed(2)}</td> 
      </tr> 
     ) 
     basketBlock = (
      <div className="col-xs-12"> 
       <div className="well"> 
        <table className="table table-responsive"> 
         <thead> 
          <tr> 
           <th>Product</th> 
           <th>Code</th> 
           <th>Quantity</th> 
           <th>Actions</th> 
           <th>Price</th> 
          </tr> 
         </thead> 
         <tbody> 
          {i.map(function(item){ 
           return <BasketItem data={item} key={item.id} />; 
          })} 
          {basketSubtotal} 
          {basketDelivery} 
          {basketTotal} 
         </tbody> 
        </table> 
       </div> 
      </div> 
     ) 

    } else { 

     basketCount = (
      <span className="basket-count"> 
       pluralize(0 Items) 
      </span> 
     ) 
     basketBlock = (
      <div className="col-xs-12"> 
       <div className="well"> 
        <h5>Add an item</h5> 
       </div> 
      </div> 
     ) 
    } 

    return(
     <div> 
      <h1>Basket {basketCount}</h1> 
      <div className="row"> 
       {basketBlock} 
      </div> 
     </div> 
    ) 
} 

}

Seiten Index - wo die Komponenten in die Ansicht montiert sind

<div class="container-fluid"> 
<div class="row"> 
    <div class="col-xs-12 col-sm-8"> 
     <%= react_component('ProductContainer', render(template: 'products/index.json.jbuilder')) %> 
    </div> 
    <div class="col-xs-12 col-sm-4 basket"> 
     <%= react_component 'BasketContainer', render(template: 'items/index.json.jbuilder') %> 
    </div> 
</div> 

Antwort

0

Sie müssen die Callback-Methode von den Eltern Komponente Kind verwenden und die Eltern auf den Erfolg Ihres Kindes Ajax-Aufruf Erfolg zu aktualisieren.

Beispiel

//Parent component 

    handleCallback: function(data) { 
     // refresh the list 
    }, 
    <somecomponent onSuccess={this.handlecallback} /> //call to child component 

    // Child Component 

    ajax.success(){ 
    this.props.onSuccess(datafromresult); 
    } 

, dass Ihr Problem :) wieder

+0

Hey Amit, vielen Dank für Ihre Antwort lösen sollte. :) Auf welche Kinder- und Elternteile beziehst du dich? –

+0

Die Komponente, die Sie aktualisieren möchten, ist die Komponente, die Sie untergeordnete haben. Also ist es einfach. In Ihrem Fall BasketContainer Component ist die Eltern und BasketItem ist Kind. :) – Amit

+0

Ich glaube nicht, dass dies funktionieren wird, da die Schaltfläche Zum Warenkorb hinzufügen in der ProductItem-Komponente und dann die HandleCallback-Funktion in der BasketContainer-Komponente ist.In Schienen werden diese separat in die Ansicht eingefügt und es scheint keine Beziehung zwischen ihnen zu bestehen. Ich füge die Ansicht zu der Frage hinzu, damit du sehen kannst, was ich meine :) –