javascript - React 单击以卸载组件消息

标签 javascript reactjs

在卸载组件时收到此消息:

Warning: Can't call setState (or forceUpdate) on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method. in NumberButton (at App.js:37)

我有一个父对象,它有一个包含按钮列表的数组。每个按钮都有一个 onclick 调用父级,父级将从列表中删除单击的按钮。

问题是该函数的目的是单击以从根本上破坏自身。该方法的完成方式不需要需要取消绑定(bind)的显式绑定(bind),因此我不认为组件中存在内存泄漏。

请告知我为什么会收到此消息、我可以做什么以及它是否是误报消息。

父类:

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是我最初的引用问题。

最佳答案

无论何时执行 setTimeout 或 setInterval,请确保在 componentWillUnMount 生命周期方法中清除它们。像下面这样的东西

 componentDidMount() {
      this.addChildTimer = setInterval(this.addChild, Settings.COMPONENT_ADD_INTERVAL);
  }

  componentWillUnMount(){
      clearInterval(this.addChildTimer);
 }

componentWillUnmount is meant to eliminate the interval that was set earlier when it mounted

像你的子组件一样明智

 updateCount() {
    this.setState((prevState, props) => {
     return { top: prevState.top + 1 }
 });
 this.updateCountTimer = setTimeout(()=> this.updateCount(), this.state.timeoutValue)
 }

 componentWillUnMount(){
   clearTimeout(this.updateCountTimer);
}

注意:避免在 setInterval 中执行 setState

关于javascript - React 单击以卸载组件消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52489325/

相关文章:

javascript - 取消选中数组中的复选框后如何删除元素?

javascript - 未检测到 ESLint 的 React Prop-Types

javascript - 与javascript的动态链接

javascript - Web 组件如何尽快获得自己的样式(宽度等)?

javascript - VueJS 不会从组件重新渲染列表

php - javascript setTimeOut - 不在嵌套的 setTimeout 上运行

javascript - 类内的 if 语句

javascript - CEP 扩展中的 React-router(例如 Premiere Pro)

android - 在发布版本上 react native AAPT错误

reactjs - 使用react-loadable实现组件延迟加载的动态路径导入