使用fetch设置react组件的状态



我正在尝试构建一个简单的天气小部件样式组件,作为Typescript和React的介绍。我有一个个人API正确发送数据,fetch正确接收API调用,并且正确地将其解析为CurrentWeather对象(?(。但是,当尝试使用CurrentWeather中的值时,它会中断。

这是我正在使用的整个.tsx文件:

import * as React from 'react';
import './WeatherWidget.css';
export interface CurrentWeather {
main: CurrentWeatherData,
name: string
}
export interface CurrentWeatherData {
temp: number,
feels_like: number,
humidity: number,
temp_min: number,
temp_max: number
}
type MyProps = {};
type MyState = {
temperature: number,
minTemperature: number,
maxTemperature: number,
feelsLikeTemp: number,
city: string,
humidity: number
};
class WeatherNow extends React.Component<MyProps, MyState> {
constructor(props:any) {
super(props);
fetch('weatherforecast/today')
.then(response => response.json() as Promise<CurrentWeather>)
.then(data => {
this.state = {
temperature: data.main.temp,
minTemperature: data.main.temp_min,
maxTemperature: data.main.temp_max,
feelsLikeTemp: data.main.feels_like,
city: data.name,
humidity: data.main.humidity
};
console.log(this.state);
});
}
render = async () => {
return (
<div className="weather-now">
<div className="weatherWidgetRow" style={{ fontSize: "32px", marginTop: "5px" }}>{this.state.temperature}°</div>
<div className="weatherWidgetRow" style={{ fontSize: "12px" }}>{this.state.minTemperature}° / {this.state.maxTemperature}°</div>
<div className="weatherWidgetRow" style={{ fontSize: "12px" }}>Feels Like: {this.state.feelsLikeTemp}°</div>
<div className="weatherWidgetRow" style={{ fontSize: "25px", marginTop: "10px" }}>{this.state.city}</div>
<div className="weatherWidgetRow" style={{ fontSize: "12px" }}>Humidity: {this.state.humidity}%</div>
</div>
);
}
}
export default WeatherNow;

我使用的是VS2022在创建typescript/react网站时使用的任何内置库。

编辑:这些是我遇到的错误。

Uncaught TypeError: Cannot read properties of undefined (reading 'main')
at WeatherNow.render (WeatherWidget.tsx:56:1)
at finishClassComponent (react-dom.development.js:18451:1)
at updateClassComponent (react-dom.development.js:18404:1)
at beginWork$1 (react-dom.development.js:20161:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:336:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:385:1)
at invokeGuardedCallback (react-dom.development.js:440:1)
at beginWork$$1 (react-dom.development.js:25738:1)
at performUnitOfWork (react-dom.development.js:24662:1)
at workLoopSync (react-dom.development.js:24638:1)
at performSyncWorkOnRoot (react-dom.development.js:24237:1)
at scheduleUpdateOnFiber (react-dom.development.js:23665:1)
at updateContainer (react-dom.development.js:27061:1)
at react-dom.development.js:27485:1
at unbatchedUpdates (react-dom.development.js:24400:1)
at legacyRenderSubtreeIntoContainer (react-dom.development.js:27484:1)
at Object.render (react-dom.development.js:27572:1)
at Module.<anonymous> (index.tsx:19:1)
at Module../src/index.tsx (index.tsx:28:1)
at __webpack_require__ (bootstrap:851:1)
at fn (bootstrap:150:1)
at Object.1 (index.ts:20:1)
at __webpack_require__ (bootstrap:851:1)
at checkDeferredModules (bootstrap:45:1)
at Array.webpackJsonpCallback [as push] (bootstrap:32:1)
at main.chunk.js:1:95
The above error occurred in the <WeatherNow> component:
in WeatherNow (at Home.tsx:21)
in div (at Home.tsx:6)
in Home (created by ConnectFunction)
in ConnectFunction (created by Context.Consumer)
in Route (at App.tsx:12)
in div (created by Container)
in Container (at Layout.tsx:10)
in Layout (at App.tsx:11)
in Unknown (at src/index.tsx:22)
in Router (created by ConnectedRouter)
in ConnectedRouter (created by Context.Consumer)
in ConnectedRouterWithContext (created by ConnectFunction)
in ConnectFunction (at src/index.tsx:21)
in Provider (at src/index.tsx:20)
Consider adding an error boundary to your tree to customize error handling behavior.
Uncaught TypeError: Cannot read properties of undefined (reading 'main')
at WeatherNow.render (WeatherWidget.tsx:56:1)
at finishClassComponent (react-dom.development.js:18451:1)
at updateClassComponent (react-dom.development.js:18404:1)
at beginWork$1 (react-dom.development.js:20161:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:336:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:385:1)
at invokeGuardedCallback (react-dom.development.js:440:1)
at beginWork$$1 (react-dom.development.js:25738:1)
at performUnitOfWork (react-dom.development.js:24662:1)
at workLoopSync (react-dom.development.js:24638:1)
at performSyncWorkOnRoot (react-dom.development.js:24237:1)
at scheduleUpdateOnFiber (react-dom.development.js:23665:1)
at updateContainer (react-dom.development.js:27061:1)
at react-dom.development.js:27485:1
at unbatchedUpdates (react-dom.development.js:24400:1)
at legacyRenderSubtreeIntoContainer (react-dom.development.js:27484:1)
at Object.render (react-dom.development.js:27572:1)
at Module.<anonymous> (index.tsx:19:1)
at Module../src/index.tsx (index.tsx:28:1)
at __webpack_require__ (bootstrap:851:1)
at fn (bootstrap:150:1)
at Object.1 (index.ts:20:1)
at __webpack_require__ (bootstrap:851:1)
at checkDeferredModules (bootstrap:45:1)
at Array.webpackJsonpCallback [as push] (bootstrap:32:1)
at main.chunk.js:1:95

第一个响应的建议代码更改也会出现相同的错误。

在componentDidMount中使用fetch而不是构造函数,并使用API调用fetch的加载状态。

import * as React from 'react';
import './WeatherWidget.css';
export interface CurrentWeather {
main: CurrentWeatherData,
name: string
}
export interface CurrentWeatherData {
temp: number,
feels_like: number,
humidity: number,
temp_min: number,
temp_max: number
}
type MyProps = {};
type MyState = {
temperature: number,
minTemperature: number,
maxTemperature: number,
feelsLikeTemp: number,
city: string,
humidity: number
};
class WeatherNow extends React.Component<MyProps, MyState> {
constructor(props:any) {
super(props);
this.state={
loading:true,
temperature:0 ,
minTemperature:0 ,
maxTemperature: 0,
feelsLikeTemp: 0,
city: 0,
humidity:0
}
}
componentDidMount(){
fetch('weatherforecast/today')
.then(response => response.json() as Promise<CurrentWeather>)
.then(data => {
let d = {
temperature: data.main.temp,
minTemperature: data.main.temp_min,
maxTemperature: data.main.temp_max,
feelsLikeTemp: data.main.feels_like,
city: data.name,
humidity: data.main.humidity
};
this.setState({...d,loading:false})

});
}
render() {
if(this.state.loading) return (<div>Loading...</div>)
return (
<div className="weather-now">
<div className="weatherWidgetRow" style={{ fontSize: "32px", marginTop: "5px" }}>{this.state.temperature}°</div>
<div className="weatherWidgetRow" style={{ fontSize: "12px" }}>{this.state.minTemperature}° / {this.state.maxTemperature}°</div>
<div className="weatherWidgetRow" style={{ fontSize: "12px" }}>Feels Like: {this.state.feelsLikeTemp}°</div>
<div className="weatherWidgetRow" style={{ fontSize: "25px", marginTop: "10px" }}>{this.state.city}</div>
<div className="weatherWidgetRow" style={{ fontSize: "12px" }}>Humidity: {this.state.humidity}%</div>
</div>
);
}
}
export default WeatherNow;

最新更新