带有 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> .