你好我上周一直在学习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”的引用。
如何通过在构造函数中保持绑定来解决该问题?
答案 0 :(得分: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);
}
它完美无缺,你知道为什么吗?