簡體   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