Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 反应不覆盖状态_Javascript_Reactjs_State_Flux - Fatal编程技术网

Javascript 反应不覆盖状态

Javascript 反应不覆盖状态,javascript,reactjs,state,flux,Javascript,Reactjs,State,Flux,我正在使用setState更改组件的状态 在我需要从状态中删除一个元素之前,它可以正常工作 让我们假设我的店里有这个: { 0: {name: foo}, 1: {name: bar} } 如果我添加另一个元素,它就可以正常工作: store[2] = {name: hohoho}; setState(store, console.log(this.state)); 通过上面的代码,我得到了预期的状态: { 0: {name: foo}, 1: {name:

我正在使用setState更改组件的状态

在我需要从状态中删除一个元素之前,它可以正常工作

让我们假设我的店里有这个:

{
    0: {name: foo},
    1: {name: bar}
}
如果我添加另一个元素,它就可以正常工作:

store[2] = {name: hohoho};
setState(store, console.log(this.state));
通过上面的代码,我得到了预期的状态:

{
    0: {name: foo},
    1: {name: bar},
    2: {name: hohoho},
}
但如果我从存储中删除其中一个元素并再次更改状态,它不会从状态中删除:

delete store[2]
如果我使用console.log(store),我会得到:

然后:

给我:

{
    0: {name: foo},
    1: {name: bar},
    2: {name: hohoho},
}
但比这更奇怪的是,如果我向存储中添加另一个元素,并在之后设置状态:

store[3] = {name: heyheyhey};
setState(store, console.log(this.state));
我最终得到以下状态:

{
    0: {name: foo},
    1: {name: bar},
    2: {name: hohoho},
    3: {name: heyheyhey}
}
即使console.log(store)提供以下信息:

{
    0: {name: foo},
    1: {name: bar},
    3: {name: heyheyhey}
}
有人能帮我理解发生了什么事吗

编辑

由于一些评论说删除可能是问题所在,我改变了从我的商店中删除的方式:

var temp = {};
for (var x in store) {
    if (x != id) {
        temp[x] = store[x];
    }
}
store= temp;

但我仍然遇到同样的问题。

回答我在评论中提到的问题
Delete
不会像关键字让你觉得那样释放内存

与一般的看法不同,delete操作符与直接释放内存无关。内存管理是通过中断引用间接完成的

因此,您所要做的就是将其替换为新对象,而不是修改旧对象

编辑:

试试这样的

cloneObject(obj) {
        if (null == obj || "object" != typeof obj) return obj;
        var copy = obj.constructor();
        for (var attr in obj) {
            if (obj.hasOwnProperty(attr)) {
                copy[attr] = obj[attr];
            }
        }
        return copy;
}

我认为您错误地使用了第二个
setState
参数。。 你应该知道:

setState()不会立即改变this.state,但会创建挂起的状态转换。调用此方法后访问this.state可能会返回现有值

setState
的第二个参数是回调:

此外,还可以提供一个可选的回调函数,该函数在setState完成并重新呈现组件后执行。 因此,您的回调应该类似于:

或其简短版本:

setState(store, console.log)

否则,您只需记录当前类状态并返回
undefined
作为第二个参数(回调)

您可以使用
undefined
而不是delete:

const changes = [
  {
    title: 'add 2',
    update: state => Object.assign({}, state, { 2: { name: 'hohoho' } }),
  },
  {
    title: 'remove 2',
    update: state => Object.assign({}, state, { 2: undefined }),
  },
  {
    title: 'add 3',
    update: state => Object.assign({}, state, { 3: { name: 'heyheyhey' } }),
  },
];

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      0: { name: 'foo' },
      1: { name: 'bar' },
    };
  }

  update(step) {
    this.setState(changes[step].update);
  }

  componentDidMount() {
    setTimeout(this.update.bind(this, 0), 2000);
    setTimeout(this.update.bind(this, 1), 4000);
    setTimeout(this.update.bind(this, 2), 6000);
  }

  render() {
    return (
      <pre>
        {JSON.stringify(this.state, null, 2)}
      </pre>
    );
  }
}
常量更改=[
{
标题:“添加2”,
更新:state=>Object.assign({},state,{2:{name:'hohoho'}}),
},
{
标题:“删除2”,
update:state=>Object.assign({},state,{2:undefined}),
},
{
标题:“添加3”,
更新:state=>Object.assign({},state,{3:{name:'heyheyhey'}}),
},
];
类应用程序扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
0:{name:'foo'},
1:{name:'bar'},
};
}
更新(步骤){
this.setState(更改[步骤].update);
}
componentDidMount(){
setTimeout(this.update.bind(this,0),2000);
setTimeout(this.update.bind(this,1),4000);
setTimeout(this.update.bind(this,2),6000);
}
render(){
返回(
{JSON.stringify(this.state,null,2)}
);
}
}
请在此处尝试:


顺便说一句,当您执行
this.setState({a:something})
时,实际上并没有将整个状态精确地设置为
{a:something}
,而是只更新某些属性(在这种特殊情况下,只更新
a
属性).

每次生成一个新对象,而不是直接改变状态对象。生成一个新对象是什么意思?你能详细说明一下吗?那是因为
delete
不像你想象的那样释放内存。更新了答案
store
变量中有什么?它引用与state相同的对象吗?执行类似于
constnextstore=Object.assign({},store)的操作;删除nextStore[2];设置状态(nextStore)解决您的问题?如果是这样的话,那么你很可能变异了同一个对象。它仍然不起作用。用更新的代码更新了答案。@Rafaelantnes仅用
=
设置值不会复制对象的新副本。这仍然是参考,也不起作用。我通过在使用setState之前直接设置状态来解决这个问题。@RafaelAntunes不会直接改变状态。只能使用setState来更新状态。通过将
undefined
赋值给要排除的键来查看我的答案。如果您阅读了当我添加另一个元素时,我添加了另一个元素而没有删除上一个元素的部分。您应该再次阅读我的答案,您使用的setState方法错误。转发到回调的参数是您的最终状态。您甚至在设置状态之前就调用了
console.log
。。。。
setState(store, (newState) => console.log(newState);
setState(store, console.log)
const changes = [
  {
    title: 'add 2',
    update: state => Object.assign({}, state, { 2: { name: 'hohoho' } }),
  },
  {
    title: 'remove 2',
    update: state => Object.assign({}, state, { 2: undefined }),
  },
  {
    title: 'add 3',
    update: state => Object.assign({}, state, { 3: { name: 'heyheyhey' } }),
  },
];

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      0: { name: 'foo' },
      1: { name: 'bar' },
    };
  }

  update(step) {
    this.setState(changes[step].update);
  }

  componentDidMount() {
    setTimeout(this.update.bind(this, 0), 2000);
    setTimeout(this.update.bind(this, 1), 4000);
    setTimeout(this.update.bind(this, 2), 6000);
  }

  render() {
    return (
      <pre>
        {JSON.stringify(this.state, null, 2)}
      </pre>
    );
  }
}