繁体   English   中英

反应事件监听器并重新安装

[英]React event listener and remounting

您好,自上周以来我一直在学习React,我解决了一个问题,但是我试图理解为什么它可以解决我的问题。

这是代码示例:

export default class ExampleComponent extends Component{

    constructor(...arg){
        super(...arg);
        this.goToNextPage = this.goToNextPage.bind(this);
        this.state = { currentPage: 1, 
                       chapterImages: []};
    }

    goToNextPage(){
        this.setState({
          ...this.state,
          currentPage: R.inc(this.state.currentPage)
        });
    }

    render(){
        return (<button onClick={this.goToNextPage}>next</button>)
    }
}

我有类似的东西。 在我的真实代码中,我正在进行ajax调用,这是我的组件被卸载并重新安装的原因……最后,当我单击按钮时,出现以下错误:

Warning: setState(...): Can only update a mounted or mounting component.
This usually means you called setState() on an unmounted component.
This is a no-op. 

但是如果我从构造函数中删除这一行:

this.goToNextPage = this.goToNextPage.bind(this);

并将render方法中的行修改为此:

return (<button onClick={this.goToNextPage.bind(this)}>next</button>)

它的工作原理完美,但我不知道为什么会收到上述错误。

我走这条路是因为卸载组件时,它会在按钮单击侦听器中保留对绑定方法“ goToNextPage”的引用。

如何通过将绑定保留在构造函数中来解决该问题?

这是我真正的代码类:

export default class MangaChapter extends Component{

  constructor(...arg){
    super(...arg);
    this._getPageId = R.prop('pageId');
    this._getPages = R.prop('pages');
    this._generatePageMenuItem = (pageId) => (<MenuItem key={pageId} value={pageId} primaryText={`${pageId}`} />);
    this._pageToMenuItem = R.compose(this._generatePageMenuItem, this._getPageId);
    this._getMangaPageMenuItems = R.compose(R.map(this._pageToMenuItem), this._getPages);
    this._toImageNode = (chapterPage) => (<img src={chapterPage.url} style={{display: 'block', margin: '0 auto'}}/>)
    this._preloadImage = (chapterPage) => new Image().src = chapterPage.url;
    this._preloadImages = R.forEach(this._preloadImage);
    this._getImagePage = R.compose(R.map(this._toImageNode), this._preloadImages, this._getPages);
    this.state = { currentPage: 1, chapterImages: this._getImagePage(this.props.chapter) };
    this.goToPreviousPage = this.goToPreviousPage.bind(this);
    this.goToNextPage = this.goToNextPage.bind(this);
  }
  componentWillMount(){
    this.props.getChapter(this.props.params.mangaId, this.props.params.chapterNum);
  }

  componentWillUnmount(){
    console.log('UNMOUNT');
  }

  componentWillReceiveProps(nextProps){
    const { chapter } = nextProps;
    this.state = { currentPage: 1, chapterImages: this._getImagePage(chapter) };
  }

  handleChange(event, index, currentPage){
    this.setState({currentPage});
  };

  goToPreviousPage(){
    this.setState({
      currentPage: R.dec(this.state.currentPage)
    });
  }

  goToNextPage(){
    this.setState({
      currentPage: R.inc(this.state.currentPage)
    });
  }

  displayPage(){
    return this.state.chapterImages[R.dec(this.state.currentPage)]
  }

  componentDidMount(){

  }

  render(){
    const { chapter, loading } = this.props;
    const chapterName = chapter.name;
    const chapterNum = this.props.params.chapterNum;

    if(loading) return (<CircularProgress size={80} thickness={5} style={loadingStyle} />);

    return (
      <div>
        <h2 style={{textAlign: 'center'}}>Chapter { chapterNum } : { chapterName } </h2>
        <div>
          {this.displayPage()}
        </div>
        <div>
        <br/>
          <Row  style={{textAlign: 'center'}}>
            <Col sm={4}>
              <RaisedButton
                label="Previous"
                primary={true}
                icon={<ChevronLeft />}
                onClick={this.goToPreviousPage}
              />
            </Col>
            <Col sm={4}>
              Page
              <SelectField
                value={""}
                onChange={this.handleChange.bind(this)}
                style={{width: '80px', display: 'inline-block'}}
                value={this.state.currentPage}
              >
                {this._getMangaPageMenuItems(chapter)}
              </SelectField>
              of { chapter.pages.length }
            </Col >
            <Col sm={4}>
              <RaisedButton
                labelPosition="before"
                label="Next"
                primary={true}
                icon={<ChevronRight />}
                style = {{display: 'inline-block'}}
                onClick={this.goToNextPage}
              />
            </Col>
          </Row>
        </div>
      </div>
    );
  }
}

问题在于构造函数中的这两个方法:

    this.goToPreviousPage = this.goToPreviousPage.bind(this);
    this.goToNextPage = this.goToNextPage.bind(this);

如果我这样做,如果我将这些方法放在这样的componentDidMount方法中,则会收到类似上面的错误:

  componentDidMount(){
    this.goToPreviousPage = this.goToPreviousPage.bind(this);
    this.goToNextPage = this.goToNextPage.bind(this);
  }

它运作完美,你知道为什么吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM