2017-01-02 6 views
0

Здравствуйте, я изучаю React с прошлой недели, и я решил проблему, но я пытаюсь понять, почему она решила мою проблему.React event listener и remounting

Вот пример кода:

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); 

и изменить строку в методе визуализации с этим:

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

работы это прекрасно, но я не знаю, почему я получаю ошибку выше.

Я пошел по этому маршруту, потому что когда мой компонент размонтирован, он сохраняет ссылку связанного метода «goToNextPage» в прослушивателе кнопки.

Как решить эту проблему, сохранив привязку в конструкторе?

+0

В чем причина размонтирования компонента? возможно, более верный пример кода жизни может оказаться полезным. Кстати, нет необходимости клонировать состояние при использовании 'setState()', только передавать ключи, требующие обновления. –

+0

Вы как-то размонтируете этот компонент после вызова onClick, скорее всего, связанного с каким-то кодом вне самого компонента. Я вижу, что это кнопка, она в форме, которая отправляется по клику? –

+0

Причина, по которой мой компонент отключен, заключается в том, что когда я делаю вызов ajax, я показываю значок загрузки на верхнем уровне древовидного компонента, и поэтому он отключает мой компонент, который находится на более низком уровне древовидной составляющей, я думаю это причина того, почему мой компонент отключен и перемонтирован. Спасибо за помощь ребята. –

ответ

0

Вот мой реальный код класс:

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); 
    } 

Он отлично работает, вы знаете, почему?