反应不覆盖状态
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
并没有像关键字使您认为的那样释放内存。
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
属性 会更新)。
我正在使用 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
并没有像关键字使您认为的那样释放内存。
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
属性 会更新)。