带有 React 的 SPFX Webpart:无法设置自己的 class 状态
SPFX Webpart with React: Can not set own class states
我有一个应用程序应该从打开的 api 中获取一些位置天气数据。用户可以输入位置。
我有 2 个文件 WeatherAppWebPart.ts 和 WeatherApp.tsx:
我遇到的问题是,我无法在我的 WeatherApp.tsx 中设置自己的状态,只需使用从上面传递到我的 class 的属性(但不设置自己的状态并使用它们作为我 class).
中的道具
例如当我使用 this.state.date 时,我收到错误消息:
Property 'date' does not exist on type 'Readonly<{}>'.
这是为什么?
WeatherAppWebPart.ts:
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version } from '@microsoft/sp-core-library';
import {
IPropertyPaneConfiguration,
PropertyPaneTextField,
PropertyPaneCheckbox,
PropertyPaneDropdown,
PropertyPaneToggle,
PropertyPaneButton,
PropertyPaneButtonType
} from '@microsoft/sp-property-pane';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import getWeatherData from './getWeatherData';
import * as strings from 'WeatherAppWebPartStrings';
import WeatherApp from './components/WeatherApp';
import { IWeatherAppProps } from './components/IWeatherAppProps';
export interface IWeatherAppWebPartProps {
description: string;
status: number;
test: string;
test1: boolean;
test2: string;
test3: boolean;
weatherData: any;
}
export default class WeatherAppWebPart extends BaseClientSideWebPart <IWeatherAppWebPartProps> {
public render(): void {
const element: React.ReactElement<IWeatherAppProps> = React.createElement(
WeatherApp,
{
description: this.properties.description,
status: this.properties.status,
weatherData: this.properties.weatherData
}
);
ReactDom.render(element, this.domElement);
}
protected onDispose(): void {
ReactDom.unmountComponentAtNode(this.domElement);
}
protected get dataVersion(): Version {
return Version.parse('1.0');
}
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return {
pages: [
{
header: {
description: strings.PropertyPaneDescription
},
groups: [
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyPaneTextField('description', {
label: 'Bitte geben Sie den Ort ein:'
}),
PropertyPaneButton('weatherButton',
{
text: "Daten anfordern",
buttonType: PropertyPaneButtonType.Normal,
onClick: () => getWeatherData(this.properties.description)
.then(data => {
console.log("Data:", data);
this.properties.status = data.status;
this.properties.weatherData = data;
})
}),
]
}
]
}
]
};
}
}
函数获取天气数据:
import axios from 'axios';
axios.defaults.headers.post['Content-Type'] ='application/json;charset=utf-8';
axios.defaults.headers.post['Access-Control-Allow-Origin'] = '*';
const apiKey = 'cf6d62de8a7d61a47748214306d35d4e';
let cityName = '';
let apiEndpoint = `http://api.openweathermap.org/data/2.5/weather?q=${cityName}&APPID=${apiKey}`;
export default async function getWeatherData(cityName) {
apiEndpoint = `https://api.openweathermap.org/data/2.5/weather?q=${cityName}&APPID=${apiKey}`;
try {
const response = await axios.get(apiEndpoint);
return response;
} catch (error) {
return error;
} finally {
console.log("Function getWeatherData() executed")
}
}
WeatherApp.tsx:
import * as React from 'react';
import styles from './WeatherApp.module.scss';
import { IWeatherAppProps } from './IWeatherAppProps';
import { escape } from '@microsoft/sp-lodash-subset';
import getWeatherData from '../getWeatherData';
export default class WeatherApp extends React.Component<IWeatherAppProps, {}> {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
public render(): React.ReactElement<IWeatherAppProps> {
console.log("This:", this);
let weatherResponse;
if (this.props.status === 200) {
console.log("Status state:", this.props.status);
// weatherResponse = <div>{this.state.status}</div>
} else {
weatherResponse = <div>Noch keine Daten.</div>
}
return (
<div className={ styles.weatherApp }>
<div className={ styles.container }>
<div className={ styles.row }>
<div className={ styles.column }>
<span className={ styles.title }>Welcome to SharePoint Weather App!</span>
<p className={ styles.subTitle }>Get Weather data from different locations.</p>
<h2>Es ist {this.state.date.toLocaleTimeString()}.</h2>
<p className={ styles.description }>{escape(this.props.description)}</p>
<button className={ styles.button } onClick={() => getWeatherData(this.props.description).then(data => {
console.log("Data Status:", data.status);
this.setState({status: data.status});
this.setState({weatherData: data});
})}>Get Data</button>
<div id="response">
{weatherResponse}
</div>
</div>
</div>
</div>
</div>
);
}
}
试着改变一下
export default class WeatherApp extends React.Component<IWeatherAppProps, {}>
到
export default class WeatherApp extends React.Component<IWeatherAppProps, any>
.
我有一个应用程序应该从打开的 api 中获取一些位置天气数据。用户可以输入位置。
我有 2 个文件 WeatherAppWebPart.ts 和 WeatherApp.tsx:
我遇到的问题是,我无法在我的 WeatherApp.tsx 中设置自己的状态,只需使用从上面传递到我的 class 的属性(但不设置自己的状态并使用它们作为我 class).
中的道具例如当我使用 this.state.date 时,我收到错误消息:
Property 'date' does not exist on type 'Readonly<{}>'.
这是为什么?
WeatherAppWebPart.ts:
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version } from '@microsoft/sp-core-library';
import {
IPropertyPaneConfiguration,
PropertyPaneTextField,
PropertyPaneCheckbox,
PropertyPaneDropdown,
PropertyPaneToggle,
PropertyPaneButton,
PropertyPaneButtonType
} from '@microsoft/sp-property-pane';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import getWeatherData from './getWeatherData';
import * as strings from 'WeatherAppWebPartStrings';
import WeatherApp from './components/WeatherApp';
import { IWeatherAppProps } from './components/IWeatherAppProps';
export interface IWeatherAppWebPartProps {
description: string;
status: number;
test: string;
test1: boolean;
test2: string;
test3: boolean;
weatherData: any;
}
export default class WeatherAppWebPart extends BaseClientSideWebPart <IWeatherAppWebPartProps> {
public render(): void {
const element: React.ReactElement<IWeatherAppProps> = React.createElement(
WeatherApp,
{
description: this.properties.description,
status: this.properties.status,
weatherData: this.properties.weatherData
}
);
ReactDom.render(element, this.domElement);
}
protected onDispose(): void {
ReactDom.unmountComponentAtNode(this.domElement);
}
protected get dataVersion(): Version {
return Version.parse('1.0');
}
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return {
pages: [
{
header: {
description: strings.PropertyPaneDescription
},
groups: [
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyPaneTextField('description', {
label: 'Bitte geben Sie den Ort ein:'
}),
PropertyPaneButton('weatherButton',
{
text: "Daten anfordern",
buttonType: PropertyPaneButtonType.Normal,
onClick: () => getWeatherData(this.properties.description)
.then(data => {
console.log("Data:", data);
this.properties.status = data.status;
this.properties.weatherData = data;
})
}),
]
}
]
}
]
};
}
}
函数获取天气数据:
import axios from 'axios';
axios.defaults.headers.post['Content-Type'] ='application/json;charset=utf-8';
axios.defaults.headers.post['Access-Control-Allow-Origin'] = '*';
const apiKey = 'cf6d62de8a7d61a47748214306d35d4e';
let cityName = '';
let apiEndpoint = `http://api.openweathermap.org/data/2.5/weather?q=${cityName}&APPID=${apiKey}`;
export default async function getWeatherData(cityName) {
apiEndpoint = `https://api.openweathermap.org/data/2.5/weather?q=${cityName}&APPID=${apiKey}`;
try {
const response = await axios.get(apiEndpoint);
return response;
} catch (error) {
return error;
} finally {
console.log("Function getWeatherData() executed")
}
}
WeatherApp.tsx:
import * as React from 'react';
import styles from './WeatherApp.module.scss';
import { IWeatherAppProps } from './IWeatherAppProps';
import { escape } from '@microsoft/sp-lodash-subset';
import getWeatherData from '../getWeatherData';
export default class WeatherApp extends React.Component<IWeatherAppProps, {}> {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
public render(): React.ReactElement<IWeatherAppProps> {
console.log("This:", this);
let weatherResponse;
if (this.props.status === 200) {
console.log("Status state:", this.props.status);
// weatherResponse = <div>{this.state.status}</div>
} else {
weatherResponse = <div>Noch keine Daten.</div>
}
return (
<div className={ styles.weatherApp }>
<div className={ styles.container }>
<div className={ styles.row }>
<div className={ styles.column }>
<span className={ styles.title }>Welcome to SharePoint Weather App!</span>
<p className={ styles.subTitle }>Get Weather data from different locations.</p>
<h2>Es ist {this.state.date.toLocaleTimeString()}.</h2>
<p className={ styles.description }>{escape(this.props.description)}</p>
<button className={ styles.button } onClick={() => getWeatherData(this.props.description).then(data => {
console.log("Data Status:", data.status);
this.setState({status: data.status});
this.setState({weatherData: data});
})}>Get Data</button>
<div id="response">
{weatherResponse}
</div>
</div>
</div>
</div>
</div>
);
}
}
试着改变一下
export default class WeatherApp extends React.Component<IWeatherAppProps, {}>
到
export default class WeatherApp extends React.Component<IWeatherAppProps, any>
.