刚开始使用 react,很多属性、方法不是很熟。在此记录下我所遇到的问题及解决方法。
我在 componentWillMount() 中调用了一个异步函数,在返回结果中调用 this.setState() 来保存数据,在 render() 中使用 this.state.article 时,显示为 undefined。代码如下:
componentWillMount() {
console.log('componentWillMount called')
let _ = this
// 获取当前文章 ID;
let postID = utils.getID(ARTICLE)
/**
* @description 获取、渲染文章内容
* @param {Number} postID - 当前文章 ID
*/
postIO.getDetail(postID).then(res => {
if (res.status === 200) {
console.log('asynchronous called')
let data = res.data
_.setState({
article: {...data},
})
}
})
}
render() {
console.log('render called')
return (
<div></div>
)
}
可以看到控制台打印信息:
componentWillMount called
render called
asynchronous called
render called
这里可以得出:调用完 componentWillMount() 后,执行 render(),这时 componentWillMount 中的回调函数也执行完毕,更新数据后再次调用 render。
这个问题原因:首先,异步函数本身就是不会等前一个任务结束后再执行后一个函数,而是在执行其回调函数的同时就开始执行后一个函数了。因此,在调用完 componentWillMount 函数后,执行 postIO.getDetail(postID).then(res => {}),同时执行 render()。
可能导致的问题:在 componentWillMount 中的回调函数中调用 this.setState({article: {...data}}),第一次调用 render 时,是获取不到 this.state.article 的值的,这样就会引起报错。
解决方法:
增加一个加载状态,默认为 false,调用 componentWillMount() 时,设置为 true,当这个加载状态是 true 时,暂不渲染,当回调函数执行完毕后,设置为 false,此时再调用 render();
完整代码如下:
constructor(props) {
super(props)
this.state = {
article: {},
isLoading: false,
}
}
componentWillMount() {
let _ = this
// 获取当前文章 ID;
let postID = utils.getID(ARTICLE)
_.setState({isLoading: true})
/**
* @description 获取、渲染文章内容
* @param {Number} postID - 当前文章 ID
*/
postIO.getDetail(postID).then(res => {
if (res.status === 200) {
console.log('asynchronous called')
let data = res.data
_.setState({
article: {...data},
isLoading: false
})
}
})
}
render() {
let {isLoading} = this.state
if (isLoading) {
return <p>isLoading...</p>
}
return (
<div></div>
)
}