反应不覆盖状态

React not overwriting state

我正在使用 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}
}

然后:

setState(store, console.log(this.state))

给我:

{
    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 并没有像关键字使您认为的那样释放内存。

根据MDN Delete

Unlike what common belief suggests, the delete operator has nothing to do with directly freeing memory. Memory management is done indirectly via breaking references

所以你所要做的就是用一个新对象替换它,而不是修改旧对象。

编辑:

尝试这样的事情

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() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value.

setState的第二个参数是回调:

In addition, you can supply an optional callback function that is executed once setState is completed and the component is re-rendered. So your callback should be something like:

setState(store, (newState) => console.log(newState);

或者它的简短版本:

setState(store, console.log)

否则你只会记录当前 class 状态并返回 undefined 作为第二个参数(回调)

您可以使用 undefined 而不是删除:

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

在这里试试:https://jsfiddle.net/jprogd/062z1kqd/2/

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