如何删除特定的子React组件? [英] How do I delete specific child React components?

查看:77
本文介绍了如何删除特定的子React组件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

当我从 ServiceList 中删除​​子 ServiceItem 组件时组件,我遇到的问题是列表中的最后一个 ServiceItem 被删除而不是目标 ServiceItem 。上面的JSFiddle链接有助于理解这个问题,只需确保在输入字段中输入一些可识别的信息,这样就可以看到被删除的内容。



我如何修复我的应用程序,以便删除相应的组件?

  var ServiceForm = React.createClass({
render:function (){
return(
< form onSubmit = {this.handleFormSubmission}>
{this.renderServiceItemList()}
< div className =btn btn-default btn-smonClick = {this.addServiceItem}> +追加新服务项< / div>
< button type =submitclassName =btn btn-success btn-lg pull-right>提交< / 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>没有服务项目,点击下面添加新服务项目!< / div> ;;
} else {
content = this.props.serviceItems.map(this.props.renderServiceItem);
}


返回(
< 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>服务项目< / label>
< select multiple ref =service_typesclassName =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>客户< / label>
< select ref =customerclassName =form-control>
< option> Troy< / option>
<选项> Dave和LT; /选项>
< option> Brandon< / option>
< / select>
< / div>
< / div>

< div className =col-sm-3>
< div className =form-group>
< label>制造商< / label>
< div className =input-group>
< input ref =manufacturertype =textclassName =form-control/>
< / div>
< / div>
< / div>


< div className =col-sm-3>
< div className =form-group>
< label>模型< / label>
< div className =input-group>
< input ref =modeltype =textclassName =form-control/>
< / div>
< a href =#onClick = {this.props.removeServiceItem}>
< span aria-hidden =trueclassName =remove-fieldsonClick = {this.props.removeServiceItem}>& times;< / span>
< / a>
< / div>
< / div>
< / div>
);
},

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

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
}
}

});
返回(服务);
},

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(值);
}
});





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


解决方案

您的问题出在您的 key = {i}



反应列表要求项目的键对项目是唯一的, 无论如何列表中项目的位置 。这允许在更新的情况下对列表进行智能管理。



React将不会正确呈现以下更新:

 来自:收件人:
姓名:钥匙:姓名:钥匙:
比尔0比尔0
查理1戴夫1
戴夫2

因为反应认为查理记录没有变化(因为密钥没有变化)。



我建议你从检索到的服务项中输入某种ID作为密钥。



在名称上,例如

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

在这种情况下,React将正确呈现更新(因为键是唯一的项目)。


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. 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.

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}.

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:

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.

On name, e.g.

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组件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆