Javascript 从ReactJS数组中删除有状态元素

Javascript 从ReactJS数组中删除有状态元素,javascript,reactjs,Javascript,Reactjs,我在删除React数组中的有状态元素时遇到问题。在以下示例中,如果单击第二个元素(“B”)上的“切换”,您将看到: 条目id:0名称:A处于活动状态切换删除 条目id:1名称:B未激活切换删除 条目id:2名称:C处于活动状态切换删除 如果现在单击第一个元素(“A”)上的“删除”: 条目id:0名称:B处于活动状态切换删除 条目id:1名称:C未激活切换删除 B已更改,但我只想删除A,而不影响任何其他元素。根据文档,我有一个键,并尝试使用带有字符串前缀的键,但没有帮助 有没有办法在不将state

我在删除React数组中的有状态元素时遇到问题。在以下示例中,如果单击第二个元素(“B”)上的“切换”,您将看到:

条目id:0名称:A处于活动状态切换删除

条目id:1名称:B未激活切换删除

条目id:2名称:C处于活动状态切换删除

如果现在单击第一个元素(“A”)上的“删除”:

条目id:0名称:B处于活动状态切换删除

条目id:1名称:C未激活切换删除

B已更改,但我只想删除A,而不影响任何其他元素。根据文档,我有一个
,并尝试使用带有字符串前缀的键,但没有帮助

有没有办法在不将state向上推至
TestContainer
的情况下执行此操作?(在我的实际情况中,我有许多不同的元素,具有不同类型的状态)


var TestLine=React.createClass({
getInitialState:函数(){
返回{active:true};
},
handleLineRemove:函数(e){
this.props.processLineRemove(this.props.id);
},
TogCollective:函数(e){
this.setState({active:!this.state.active};
},
render:function(){
返回(

条目id:{this.props.id}名称:{this.props.name}
{this.state.active?“处于活动状态”:“未处于活动状态”}
切换
去除

); } }); var TestContainer=React.createClass({ getInitialState:函数(){ 返回{data:{行:['A','B','C']}; }, processLineRemove:函数(索引){ var new_lines=this.state.data.lines.slice(0); 新的拼接线(索引1); var newState=React.addons.update(this.state.data{ 行:{$set:new_行} }); this.setState({data:newState}); }, render:function(){ 变量体=[]; 对于(var i=0;i
如果您有一个项目列表,并且您知道项目将被随机编辑,我不会创建这样的键。我宁愿创建唯一且
不会在列表更改时与其他键重叠的键。一个简单的随机键生成器就足够了

为什么?让我们看一下每一步

首先是这样的

条目id:0名称:A处于活动状态切换删除

条目id:1名称:B未激活切换删除

条目id:2名称:C处于活动状态切换删除

第二个看起来像这样

条目id:0名称:B未处于活动状态切换删除

条目id:1名称:C处于活动状态切换删除

现在,是时候把这两个,并找出什么改变。它将比较组件和键

它查看第一个元素并了解“active”标志根据键设置为true。因此,它将对第二次渲染中找到的键0应用相同的设置。对于其余元素,依此类推

因此,如果您的密钥在更改时不重叠,则可以避免此问题。 这是唯一的办法。希望这有帮助

下面是一个例子来解释上述情况


当您有一个包含任意删除/插入的列表时,您不能使用索引作为键。在这种情况下,您可以使用实际值,因为它没有更改

var body=this.state.data.map(函数(x,i){
返回
}.约束(这个);
在更复杂的情况下,您需要一个对象数组,并为每个对象分配一个具有唯一值的属性。假设状态为
[makeItem('a')、makeItem('B')、…]

function unique(){return++unique.i};
唯一,i=0;
函数makeItem(text){return{text:text,id:unique()};};
var body=this.state.data.map(函数(x,i){
返回
}.约束(这个);

总是需要一些集中的位置来通知删除。您可以使用操作/调度程序来通知更改并将其传回,但从概念上讲,它与现有实现没有太大区别,如图所示。您需要通知拥有数据的任何组件或存储。Ele通过拥有该数组的TestContainer成功地删除了元素。但是,剩余的数组元素没有正确地重新呈现;只移动了名称标签,并且TestLine中的私有状态没有“移动”到数组中的新位置。然后,您会问两个问题——如何在不涉及e
TestContainer
以及如何正确地重新渲染。看起来答案应该会对您有所帮助。UUID解决了许多服务器每秒创建数十亿个UUID的问题,几乎没有冲突的可能性。这有点过分。@FakeRainBrigand可能更有意义,例如(使用前缀?)
<div id="test"></div>

<script type="text/jsx">

  var TestLine = React.createClass({
      getInitialState: function() {
          return {active: true};
      },
      handleLineRemove: function(e) {
        this.props.processLineRemove(this.props.id);
      },
      toggleActive: function(e) {
        this.setState({active: !this.state.active};
      },
      render: function() {
        return (
          <p>
            Entry id: {this.props.id} name: {this.props.name}
            {this.state.active ? " Is Active " : " Is Not Active " }
            <a onClick={this.toggleActive}>Toggle</a>
            &nbsp;<a onClick={this.handleLineRemove}>Remove</a>
          </p>
        );
      }
    });

     var TestContainer = React.createClass({
        getInitialState: function() {
          return {data: {lines: ['A','B','C']}};
        },
        processLineRemove: function(index) {
              var new_lines = this.state.data.lines.slice(0);
              new_lines.splice(index,1);
              var newState = React.addons.update(this.state.data, {
                lines: {$set: new_lines}
              });
          this.setState({data: newState});
        },
        render: function() {
            var body =[];
            for (var i = 0; i < this.state.data.lines.length; i++) {
                body.push(<TestLine 
                          key={i}
                          id={i}
                          name={this.state.data.lines[i]}
                          processLineRemove={this.processLineRemove} />)
            }
            return (
                <div>{body}</div>
            );
        }
    });

React.render(<TestContainer />, document.getElementById('test'));
</script>