简体   繁体   English

如何删除特定的子React组件?

[英]How do I delete specific child React components?

JSFiddle: https://jsfiddle.net/morahood/cp569zg6/38/ JSFiddle: https ://jsfiddle.net/morahood/cp569zg6/38/

When I delete a child ServiceItem component from the ServiceList component, I am running into an issue where the last ServiceItem in the list is removed instead of the targeted ServiceItem . 当我从ServiceList组件中删除子ServiceItem组件时,我遇到的问题是删除列表中的最后一个ServiceItem而不是目标ServiceItem The JSFiddle link above will help understand the issue, just make sure you enter in some identifiable information in the input fields so you can see what is getting deleted. 上面的JSFiddle链接将有助于理解该问题,只需确保在输入字段中输入一些可识别的信息,以便您可以看到要删除的内容。

How do I fix my application so that the respective component is deleted? 如何修复我的应用程序以删除相应的组件?

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" : 'test@example.com',
        "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')
);

Your issue is with your key={i} . 您的问题是您的key={i}

React lists requires the key of an item to be unique to the item, regardless of the position of the item in the list . 无论项目在列表中的位置如何,反应列表都要求项目的键对项目是唯一 This allows react to do smart management of the list in case of updates. 这允许在更新的情况下对列表进行智能管理。

React will NOT render the following update correctly: React不会正确呈现以下更新:

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

Because react thinks that the Charlie record is unchanged (because the key is unchanged). 因为反应认为查理记录没有变化(因为密钥没有变化)。

I would advise you to put some sort of ID from the service-item retrieved as key. 我建议你从检索的服务项中输入某种ID作为密钥。

On name, eg 在名字上,例如

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

React will render the update correctly in this case (because key is unique to the item). 在这种情况下,React将正确呈现更新(因为键对于项是唯一的)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM