2016-04-11 8 views
0

Ich habe eine Rails-App mit zwei reactJS-Komponenten (nicht Eltern/Kind), die derzeit über eine globale Ereignisse Pub/Sub-System kommunizieren.this.setState re-rendering nicht anzeigen ReactJS und Ruby on Rails

Wenn ich jedoch this.setState({ items: this.props.items }) ausführen bekomme ich die Nachricht Cannot read property 'items' of undefined.

Jede Hilfe, die Leute anbieten können, warum ich diesen Fehler bekommen könnte, würde sehr geschätzt werden.

Das Basis-Setup ich habe, ist:

BasketContainer - abonniert zwei Ereignisse

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.token = PubSub.subscribe('ADD_BASKET', this.handleUpdate) 
    this.token = PubSub.subscribe('REMOVE_ITEM', this.handleUpdate) 
    this.calculateTotals(); 
} 

componentWillUnmount() { 
PubSub.unsubscribe(this.token) 
} 

handleUpdate(msg, data){ 
    console.log(msg) 
    this.setState({ 
     items:this.props.items // ERROR MESSAGE - Cannot read property 'items' of undefined 
    }) 
} 
.... Rest of file 

ProductItem - In den Warenkorb Event Publisher

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(data) { 
      PubSub.publish('ADD_BASKET', data); // THIS WORKS FINE 
      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 - entfernen von Basket Publisher

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(data) { 
      PubSub.publish('REMOVE_ITEM', data); // THIS WORKS FINE 
     }, 
     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> 
    ) 
} 
} 

Antwort

1

denke ich, das Problem mit der folgenden Codezeile ist

this.token = PubSub.subscribe('ADD_BASKET', this.handleUpdate) 

Die Funktion, die Sie als param sind vorbei muss mit 'this'

this.token = PubSub.subscribe('ADD_BASKET', this.handleUpdate.bind(this)) 

Das Gleiche gilt für remove_item werden binded Aktion. Dann sollte es gut gehen :)

+0

Danke für Ihre Hilfe - das ist die Beseitigung der Fehler bekommt aber setState scheint nicht die Component-Rendering wieder werden, eine Idee woran das liegen könnte? :) –

+0

In BasketContainer, componentWillMount() setzen Sie den Status mit this.props.items, in handleUpdate() machen Sie dasselbe. Also ändert sich der Staat dort nicht. –

+0

componentWillMount wird aufgerufen, bevor die Rendermethode ausgeführt wird. Es ist wichtig zu beachten, dass das Setzen des Status in dieser Phase kein erneutes Rendering auslöst. In handleUpdate() müssen Sie this.state.items gemäß dem Parameter 'data' bearbeiten und dann den Status entsprechend festlegen. –

0

Sie sollen die Eigenschaft items an BasketContainer von seiner Elternklasse übergeben. Deshalb erhalten Sie Fehler Cannot read property 'items' of undefined.

Update: die Zeile, wo Sie den Fehler erwähnt haben, der Fehler, den Sie erhalten, ist wegen der falschen Referenz this;

versuchen so etwas wie:

handleUpdate(msg, data){ 
    var self = this; 
    this.setState({ 
     items: self.props.items // Here get props from self variable 
    }) 
} 
+0

Danke für Ihre Hilfe. BasketContainer hat keine Elternklasse, weshalb ich das Pub/Sub-Ereignissystem verwende.Rohit's Kommentar unten hat den Fehler behoben, aber jetzt wird setState nicht neu gerendert. Irgendeine Idee warum das sein könnte? –