是否可以访问render()
之外的状态变量,但是可以在React自定义组件方法中访问状态变量?
componentDidMount() {
fetch(
"some url here"
)
.then(res => res.json())
.then(json => {
const days = this.getRainyDays(json)
this.setState({
data: json,
rainyDays: days
});
});
}
getRainyDays = (data) => {
console.log('data inside getRainyDays', this.state.data) // this.state.data is undefined here
console.log('data inside getRainyDays2', data) // data returns json fine
}
render() {
console.log(this.state.data) // this.state.data is fine too.
return (
<div className="App">
<header className="App-header">
Calendar showing {this.state.rainyDays} rainy days
</header>
<Year weatherData={this.state.data} />
<Weather />
</div>
);
}
答案 0 :(得分:1)
是的,可以在render
方法之外的组件内部访问状态。
根据React
文档:
setState()
并不总是立即更新组件。它可能会批量更新或将更新推迟到以后。这使得在调用this.state
之后立即阅读setState()
可能是一个陷阱。
由于您的初始状态很可能没有将data
属性设置为某个值,因此其返回为undefined
。
您试图在this.state.data
内部访问getRainyDays
之前访问this.setState
内部的componentDidMount
:
componentDidMount() {
fetch(...)
.then(json => {
const days = this.getRainyDays(json)
this.setState(...)
})
}
getRainyDays = (data) => {
console.log('data inside getRainyDays', this.state.data)
}
但是,即使您在this.getRainyDays
之后致电this.setState
,也不能依靠this.setState
立即更新状态。
再次根据React
文档:
将
setState()
视为请求而不是立即命令来更新组件。为了获得更好的感知性能,React可能会延迟它,然后在一次通过中更新几个组件。 React不能保证状态更改会立即应用。
但是,如果您要仔细检查状态是否正确更新,则可以将回调传递给setState
,该回调将在setState
更新组件的状态后被调用,如下所示:
componentDidMount() {
fetch(..)
.then(res => res.json())
.then(json => {
const days = this.getRainyDays(json)
this.setState({
data: json,
rainyDays: days
}, () => {
console.log('data in state', this.state.data)
});
});
}
我建议的一件事是,在返回render
之前,先检查JSX
函数内部状态是否包含正确的数据。您可能会遇到一些问题,其中某些组件需要一个项目数组并立即呈现它,但是您向其中传递了undefined
并崩溃了...
render() {
// exit early and return `null` so that nothing gets rendered
// if your API call hasn't finished
if (!this.state.data || !this.state.rainyDays) {
return null
}
return (
<div className="App">
<header className="App-header">
Calendar showing {this.state.rainyDays} rainy days
</header>
<Year weatherData={this.state.data} />
<Weather />
</div>
);
}