即使数据没有改变,我也可以使用 setState 强制重新渲染吗?我的 GUI 不会更新?
Can I force a rerender with setState even if the data hasn't changed? My GUI won't update?
所以我现在遇到的问题是第一次点击时,我的 GUI 重新呈现。但是在第二次点击时,它不会重新呈现。我相信这是因为我没有更新我的渲染通过“graphicLayers.map”绑定的“graphicLayers”的状态。无论如何,这就是我的理论(即使它适用于第一次点击?但不是第二次点击或之后的任何东西)。
我尝试强制更新 graphicLayers 的 setState,但它似乎不起作用。像这样:
let graphicLayersCopy = Object.assign([], this.state.graphicLayers);
this.setState({graphicLayers: graphicLayersCopy});
但这不起作用。我通过调试器知道它正在正确设置数据,如果我刷新(它保存状态并重新加载状态),则 GUI 会正确呈现。
有没有办法强制重新渲染一个变量,即使它没有改变值?
构造函数
constructor(props, context) {
super(props, context);
this.state = {
graphicLayers: [id1, id2, id3],
graphicLayersById: {
id1: { ... },
id2: { ... },
id3: { ... }
}
this.addLayerClick = this.addLayerClick.bind(this);
};
渲染
render() {
return (
<div>
{this.state.graphicLayers.map((id) =>
<GraphicLayer addLayerClick={this.addLayerClick.bind(this)} />
)}
</div>
);
}
addLayerClick
addLayerClick() {
... change some property in graphicLayersById dictionary ...
self.setState({ graphicLayersById: newDataHere });
}
编辑:我发现了我这边的问题,这里没有准确显示。
所以我的 addLayerClick() 实际上调用了另一个正在侦听调用的函数,并在其中设置了状态。这很奇怪,因为在回调函数中调用了 setState,但我通过将 setState 放在 addLayerClick() 本身中来让它工作。仍然不知道为什么这不起作用,但我至少会支持你们所有人
listenFunction() {
let self = this;
this.firebaseWrapper.storage.on('graphicLayersById', function (save) {
if (save) {
self.setState({ graphicLayersById: save }); // FOR SOME REASON THIS DOESN'T UPDATE THE GUI THE 2nd CLICK. The data is correct though and I see it going here on a breakpoint, but GUI won't update unless I setState in the actual button
}
else {
self.setState({ graphicLayersById: undefined });
}
});
}
实际上,您已经将 addLayerClick()
功能绑定到组件,因此您可以使用 this
而不是 self
您应该像这样修改您的代码:(大约有 2 处更改)
constructor(props, context) {
super(props, context);
this.state = {
graphicLayers: [id1, id2, id3],
graphicLayersById: {
id1: { ... },
id2: { ... },
id3: { ... }
}
// don't need to bind here anymore, since you bind it in the click
//this.addLayerClick = this.addLayerClick.bind(this);
};
addLayerClick() {
//... change some property in graphicLayersById dictionary ...
// just use 'this' here
this.setState({ graphicLayersById: newDataHere });
// the below line is NOT recommended, which is force the component to update
// this.forceUpdate(); // this line will update the component even though there's no change
}
如果这还不行,请post在这里你如何处理子组件中的onCLick
函数,如果有的话post一些错误,谢谢
希望这两种可能的方式能引起您的注意
this.setState({graphicLayersById: newDataHere} , ()=>{
console.log(this.state.graphicLayersById);
});
或
var update = require('react-addons-update');
var graphicLayers = update(this.state, {
graphicLayersById: {$set: newDataHere}
});
this.setState(graphicLayers);
在 addLayerClick()
中,您仅更新 graphicLayersById
,但渲染取决于 graphicLayers
。您也应该更新 addLayerClick()
中的 graphicLayers
状态。
addLayerClick() {
this.setState({
graphicLayers: ...
graphicLayersById: ....
});
}
附带说明一下,您不应该在 render()
中绑定方法,因为这会在每次渲染时创建一个全新的函数(并且可能会影响性能)。而不是
<GraphicLayer addLayerClick={this.addLayerClick.bind(this)} />
做
<GraphicLayer addLayerClick={this.addLayerClick} />
并在您的构造函数中保留绑定(您已有的方式)。
所以我现在遇到的问题是第一次点击时,我的 GUI 重新呈现。但是在第二次点击时,它不会重新呈现。我相信这是因为我没有更新我的渲染通过“graphicLayers.map”绑定的“graphicLayers”的状态。无论如何,这就是我的理论(即使它适用于第一次点击?但不是第二次点击或之后的任何东西)。
我尝试强制更新 graphicLayers 的 setState,但它似乎不起作用。像这样:
let graphicLayersCopy = Object.assign([], this.state.graphicLayers);
this.setState({graphicLayers: graphicLayersCopy});
但这不起作用。我通过调试器知道它正在正确设置数据,如果我刷新(它保存状态并重新加载状态),则 GUI 会正确呈现。
有没有办法强制重新渲染一个变量,即使它没有改变值?
构造函数
constructor(props, context) {
super(props, context);
this.state = {
graphicLayers: [id1, id2, id3],
graphicLayersById: {
id1: { ... },
id2: { ... },
id3: { ... }
}
this.addLayerClick = this.addLayerClick.bind(this);
};
渲染
render() {
return (
<div>
{this.state.graphicLayers.map((id) =>
<GraphicLayer addLayerClick={this.addLayerClick.bind(this)} />
)}
</div>
);
}
addLayerClick
addLayerClick() {
... change some property in graphicLayersById dictionary ...
self.setState({ graphicLayersById: newDataHere });
}
编辑:我发现了我这边的问题,这里没有准确显示。
所以我的 addLayerClick() 实际上调用了另一个正在侦听调用的函数,并在其中设置了状态。这很奇怪,因为在回调函数中调用了 setState,但我通过将 setState 放在 addLayerClick() 本身中来让它工作。仍然不知道为什么这不起作用,但我至少会支持你们所有人
listenFunction() {
let self = this;
this.firebaseWrapper.storage.on('graphicLayersById', function (save) {
if (save) {
self.setState({ graphicLayersById: save }); // FOR SOME REASON THIS DOESN'T UPDATE THE GUI THE 2nd CLICK. The data is correct though and I see it going here on a breakpoint, but GUI won't update unless I setState in the actual button
}
else {
self.setState({ graphicLayersById: undefined });
}
});
}
实际上,您已经将 addLayerClick()
功能绑定到组件,因此您可以使用 this
而不是 self
您应该像这样修改您的代码:(大约有 2 处更改)
constructor(props, context) {
super(props, context);
this.state = {
graphicLayers: [id1, id2, id3],
graphicLayersById: {
id1: { ... },
id2: { ... },
id3: { ... }
}
// don't need to bind here anymore, since you bind it in the click
//this.addLayerClick = this.addLayerClick.bind(this);
};
addLayerClick() {
//... change some property in graphicLayersById dictionary ...
// just use 'this' here
this.setState({ graphicLayersById: newDataHere });
// the below line is NOT recommended, which is force the component to update
// this.forceUpdate(); // this line will update the component even though there's no change
}
如果这还不行,请post在这里你如何处理子组件中的onCLick
函数,如果有的话post一些错误,谢谢
希望这两种可能的方式能引起您的注意
this.setState({graphicLayersById: newDataHere} , ()=>{
console.log(this.state.graphicLayersById);
});
或
var update = require('react-addons-update');
var graphicLayers = update(this.state, {
graphicLayersById: {$set: newDataHere}
});
this.setState(graphicLayers);
在 addLayerClick()
中,您仅更新 graphicLayersById
,但渲染取决于 graphicLayers
。您也应该更新 addLayerClick()
中的 graphicLayers
状态。
addLayerClick() {
this.setState({
graphicLayers: ...
graphicLayersById: ....
});
}
附带说明一下,您不应该在 render()
中绑定方法,因为这会在每次渲染时创建一个全新的函数(并且可能会影响性能)。而不是
<GraphicLayer addLayerClick={this.addLayerClick.bind(this)} />
做
<GraphicLayer addLayerClick={this.addLayerClick} />
并在您的构造函数中保留绑定(您已有的方式)。