2016-02-29 52 views
0

的jsfiddle:https://jsfiddle.net/morahood/cp569zg6/38/如何刪除特定的React組件?

當我刪除了ServiceList組件的子組件ServiceItem,我遇到了其中列表中的最後一個ServiceItem被刪除,而不是有針對性的ServiceItem的問題。上面的JSFiddle鏈接將幫助您理解問題,只需確保您在輸入字段中輸入了一些可識別的信息,以便您可以查看要刪除的內容。

如何修復我的應用程序以便刪除相應的組件?

var ServiceForm = React.createClass({ 
    render: function() { 
    return (
     <form onSubmit={ this.handleFormSubmission } > 
     { this.renderServiceItemList() } 
     <div className="btn btn-default btn-sm" onClick={ this.addServiceItem }>+ Append New Service Item</div> 
     <button type="submit" className="btn btn-success btn-lg pull-right">Submit</button> 
     </form> 
    ); 
    }, 

    getInitialState: function() { 
    return ({ 
     serviceItems: [this.renderServiceItem] 
    }); 
    }, 

    handleFormSubmission: function(event) { 
    event.preventDefault(); 
    var data = this.refs.service_item_list.getAllServiceItems(); 
    var json = { 
     "service_request" : { 
     "services" : data, 
     "additional_recipients" : '[email protected]', 
     "comments" : 'Hello world!' 
     } 
    }; 
    console.log(json); 
    }, 


    addServiceItem: function(event) { 
    var copy = this.state.serviceItems.slice(); 
    copy.push(this.renderServiceItem); 

    this.setState({ 
     serviceItems: copy 
    }); 
    }, 

    renderServiceItem: function(item, i) { 
    return (
     <ServiceItem removeServiceItem={ this.removeServiceItem } data={item} key={i} ref={"service_item_" + i} /> 
    ); 
    }, 

    removeServiceItem: function(event) { 
    var index = parseInt(event.target.value, 10); 
    var copy = this.state.serviceItems.slice(); 
    copy.splice(index, 1); 

    this.setState({ 
     serviceItems: copy 
    }); 
    }, 

    renderServiceItemList: function() { 
    return (
     <ServiceItemList serviceItems={ this.state.serviceItems } 
        renderServiceItem={ this.renderServiceItem } 
        removeServiceItem={ this.removeServiceItem } 
           ref="service_item_list" /> 
    ); 
    } 
}); 





var ServiceItemList = React.createClass({ 
    render: function() { 
    var content; 
    if (this.props.serviceItems.length < 1) { 
     content = <div className="empty-service-list">There are no service items, click on append new service item below!</div>; 
    } else { 
     content = this.props.serviceItems.map(this.props.renderServiceItem); 
    } 


    return (
     <div> 
     { content } 
     </div> 
    ); 
    }, 

    getAllServiceItems: function() { 
    var data = []; 

    for (var ref in this.refs) { 
     data.push(this.refs[ref].serializeItem()); 
    } 

    var merged = [].concat.apply([], data); 
    return(merged); 
    } 
}); 





var ServiceItem = React.createClass({ 
    render: function() { 
    return (
     <div className="row"> 
     <div className="col-sm-3"> 
      <div className="form-group service-item"> 

      <label>Service Item </label> 
      <select multiple ref="service_types" className="form-control"> 
       <option>Oil Change</option> 
       <option>Tire Rotation</option> 
       <option>New Wiper Blades</option> 
      </select> 
      </div> 
     </div> 

     <div className="col-sm-3"> 
      <div className="form-group"> 
      <label>Customer </label> 
      <select ref="customer" className="form-control"> 
       <option>Troy</option> 
       <option>Dave</option> 
       <option>Brandon</option> 
      </select> 
      </div> 
     </div>   

     <div className="col-sm-3"> 
      <div className="form-group"> 
      <label>Manufacturer </label> 
      <div className="input-group"> 
       <input ref="manufacturer" type="text" className="form-control" /> 
      </div> 
      </div> 
     </div> 


     <div className="col-sm-3"> 
      <div className="form-group"> 
      <label>Model </label> 
      <div className="input-group"> 
       <input ref="model" type="text" className="form-control" /> 
      </div> 
      <a href="#" onClick={ this.props.removeServiceItem }> 
       <span aria-hidden="true" className="remove-fields" onClick={ this.props.removeServiceItem }>&times;</span> 
      </a> 
      </div> 
     </div> 
     </div> 
    ); 
    }, 

    getInitialState: function() { 
    return({ 
     service_types: [], 
     customer: '', 
     manufacturer: '', 
     model: '' 
    }); 
    }, 

    serializeItem: function() { 
    var customer = this.refs.customer.value; 
    var manufacturer = this.refs.manufacturer.value; 
    var model = this.refs.model.value; 

    var selected = this.getSelectedServiceItems(); 

    var services = this.getSelectedServiceItems().map(function(item) { 
     return (
      { 
      "service" : { 
       "service_type" : item, 
       "customer" : customer, 
       "manufacturer" : manufacturer, 
       "model" : model 
      }  
      } 
     ) 
     }); 
    return(services); 
    }, 

    getSelectedServiceItems: function() { 
     var select = this.refs.service_types; 
     var values = [].filter.call(select.options, function (o) { 
     return o.selected; 
    }).map(function (o) { 
     return o.value; 
    }); 
    return(values); 
    } 
}); 





ReactDOM.render(
    <ServiceForm />, 
    document.getElementById('container') 
); 

回答

2

您的問題與您的key={i}

陣營名單需要一個項目的關鍵是唯一的項目,無論項目的位置列表中的。這允許在更新的情況下對列表進行智能管理。

陣營將不能正確地呈現以下更新:

From:       To: 
name:  key:    name:   key: 
Bill  0     Bill   0 
Charlie 1     Dave   1 
Dave  2 

由於反應認爲,查理記錄是不變(因爲關鍵是不變)。

我建議你把服務項目中的某些ID作爲密鑰獲取。

在名稱上,例如,

From:       To: 
name:  key:    name:   key: 
Bill  Bill    Bill   Bill 
Charlie Charlie    Dave   Dave 
Dave  Dave 

在這種情況下,React將正確呈現更新(因爲鍵對於項是唯一的)。

+0

謝謝,我仍試圖解決這個問題,但你正確地找出了我的邏輯中的差距,我只需要弄清楚如何緩解它,因爲我沒有從任何獨特的ID開始[即這些都是新紀錄,尚未提交給任何數據庫]。 – pyRabbit

+0

緩解=唯一ID,當您創建服務項目時,這也可能是時間戳。 – wintvelt