在卸载组件时获取此消息:
警告:无法在已卸载的设备上调用setState(或forceUpdate) 零件。这是空操作,但表示您的内存泄漏 应用。要修复,请取消所有订阅和异步任务 在componentWillUnmount方法中。 在NumberButton中(在App.js:37)
我有一个父母,有一个带有按钮列表的数组。每个按钮都有一个onclick
来调用父级,这将从列表中删除单击的按钮。
问题在于该函数的用途是单击以实质上破坏其自身。该方法的完成方式不需要显式绑定,而无需显式绑定就不需要解除绑定,因此我认为组件中不会存在内存泄漏。
请告知我为什么会收到此消息,我可以做什么以及如果它是假阳性消息。
父类:
class PanelDiv extends Component
{
constructor(props) {
super(props);
this.state = {items: [0]};
this.addChild = this.addChild.bind(this);
this.buttonClickHandler = this.buttonClickHandler.bind(this);
}
render()
{
return (<div id="DivBackground" onLoad={() => this.PanelLoaded()} style={{width: '100%', height: '100%', backgroundImage: "url(" + BackgroundImage + ")", backgroundSize: "cover"}}>
{
this.state.items.map((item) => (
<NumberButton key={"Nb" + item.toString()} parentClickHandler={this.buttonClickHandler} id={"Nb" + item.toString()} />
))
}
</div>);
}
componentDidMount()
{
setInterval(this.addChild, Settings.COMPONENT_ADD_INTERVAL);
}
buttonClickHandler(clientId) {
this.setState((previousState, currentProps) => ({
items: previousState.items.filter(element => {
return element.toString() !== clientId.substring(2)
}
//console.log("Matching Element: ")
)
}));
}
componentWillUnmount() {
}
addChild()
{
this.setState((previousState, currentProps) => {
if (previousState.items.length == 0)
return {items:[0]};
else
return {items: previousState.items.concat([previousState.items[previousState.items.length-1]+1])};
});
}
}
儿童班:
class NumberButton extends Component
{
constructor(props) {
super(props);
var varLeft = (0 + (Math.random() * (90-0))).toString() + '%';
var timeoutValue = Settings.BUTTON_SPEED_MIN + (Math.random() * (Settings.BUTTON_SPEED_MAX-Settings.BUTTON_SPEED_MIN));
var numberValue = Math.round(Math.random() * (Settings.MAX_NUMBER));
this.state = { clientId: props.id, wavePath: Waves[numberValue], left: varLeft, top: 0, counter: "Hello", timeoutValue: timeoutValue, numberValue: numberValue };
}
updateCount() {
this.setState((prevState, props) => {
return { top: prevState.top + 1 }
});
setTimeout(()=> this.updateCount(), this.state.timeoutValue)
}
componentDidMount()
{
this.updateCount();
//this.buttonClicked = this.buttonClicked.bind(this);
}
componentWillUnmount() {
}
render()
{
return (
<button id={this.state.clientId} onClick={() => this.buttonClicked()} style={{color: "white", fontSize: Settings.BUTTON_FONT_SIZE, fontFamily: "Verdana", border: "none", backgroundColor: "Transparent", backgroundSize: "cover", backgroundImage: "url(" + CoconutImage + ")", position: "absolute", left: this.state.left, top: this.state.top, width: Settings.BUTTON_WIDTH_AND_HEIGHT, height: Settings.BUTTON_WIDTH_AND_HEIGHT}}>
{this.state.numberValue}
</button>
);
}
buttonClicked()
{
var audio = new Audio(this.state.wavePath);
audio.play();
this.props.parentClickHandler(this.state.clientId);
}
}
This是我最初的问题,仅供参考。
答案 0 :(得分:1)
每当执行setTimeout或setInterval时,都要确保在componentWillUnMount生命周期方法中清除它们。像下面这样
Dataset<Row> testDs=ds.join(functions.broadcast(dsgrouped), dsgrouped.col("tick").equalTo(ds.col("symbol"))
.and(dsgrouped.col("Id").equalTo(ds.col("traderId")))
.and(dsgrouped.col("maxdate").equalTo(ds.col("datetime"))));
componentWillUnmount旨在消除设置的间隔 挂载时更早
像子元素一样聪明
componentDidMount() {
this.addChildTimer = setInterval(this.addChild, Settings.COMPONENT_ADD_INTERVAL);
}
componentWillUnMount(){
clearInterval(this.addChildTimer);
}
注意:避免在setInterval内执行setState
答案 1 :(得分:0)
似乎您的代码中的问题是由计时器引起的。您的代码中有setTimeout和setInterval,即使卸载了组件,它们也将执行。因此错误现在应该更清楚了(您无法为未安装的组件设置状态)。
对代码进行以下更改。
父母阶级
componentWillMount() {
this.intervalId = setInterval(this.addChild, Settings.COMPONENT_ADD_INTERVAL);
}
componentWillUnmount() {
clearInterval(this.intervalId);
}
儿童班
this.updateCountTimout = setTimeout(()=> this.updateCount(), this.state.timeoutValue);
componentWillUnmount() {
clearTimeout(this.updateCountTimout);
}