简体   繁体   English

使用 Ionic/React/Typescript 传递道具时出错 - React.FC 中的道具错误<'wrong props here'>

[英]Error when passing props with Ionic/React/Typescript - Wrong props in React.FC<'wrong props here'>

After dealing with this problem for good while I got no success.在我没有成功地解决这个问题之后。 I have been checking many questions around here but I could not find one that suits my case, so please, I would like to ask you for help.我一直在检查这里的许多问题,但我找不到适合我的情况,所以拜托,我想向你寻求帮助。

I have a problem passing my props through the <WeatherCard/> component.我在通过<WeatherCard/>组件传递道具时遇到问题。 The test application has 2 tabs and both tabs have the <WeatherCard/> being rendered.测试应用程序有 2 个选项卡,并且两个选项卡都呈现<WeatherCard/> When I hover <WeatherCard/> in Tab1.tsx Typescript shows me the wrong (unexpected) props (WeatherProps), see below:当我在 Tab1.tsx Typescript 中的 hover <WeatherCard/>向我显示错误的(意外的)道具 (WeatherProps) 时,请参见下文:

     (alias) const WeatherCard: React.FC<WeatherProps>
import WeatherCard

On the other hand, whereas when I hover <WeatherCard/> in Tab2.tsx it shows the correct props being passed, see below:另一方面,当我在 Tab2.tsx 中输入 hover <WeatherCard/>时,它显示正确的道具被传递,见下文:

         (alias) const WeatherCard: React.FC<WeatherCardProps>
 import WeatherCard

Moreover it shows the following error:此外,它显示以下错误:

[react-scripts] TS2322: Type '{ weatherIconUrl: string; [react-scripts] TS2322: 类型 '{ weatherIconUrl: string; weatherData: any;天气数据:任何; weatherVars: string[];天气变量:字符串[]; }' is not assignable to type 'IntrinsicAttributes & WeatherProps & { children?: ReactNode; }' 不可分配给类型 'IntrinsicAttributes & WeatherProps & { children?: ReactNode; }'. }'。 [react-scripts] Property 'weatherIconUrl' does not exist on type 'IntrinsicAttributes & WeatherProps & { children?: ReactNode; [react-scripts] 类型 'IntrinsicAttributes & WeatherProps & { children?: ReactNode; 上不存在属性 'weatherIconUrl' }'. }'。

I console.log the props passed in <WeatherProperty/> and these props are actually the props passed to <WeatherCard/> so, it seems like for some reason the props declared in <WeatherProperty/> are not taken into account when using Tab1我 console.log 在<WeatherProperty/>中传递的道具,这些道具实际上是传递给<WeatherCard/>的道具,因此,似乎出于某种原因,在使用 Tab1 时未考虑在<WeatherProperty/>中声明的道具

I will include the code below:我将包括以下代码:

Tab1.tsx Tab1.tsx

import {
  IonButton,
  IonButtons,
  IonCard,
  IonCardContent,
  IonCol,
  IonContent,
  IonGrid,
  IonHeader,
  IonItem,
  IonPage,
  IonRow,
  IonText,
  IonThumbnail,
  IonTitle,
  IonToolbar,
  IonLoading,
  IonAlert,
} from "@ionic/react";
import styles from "./Tab1.module.css";
import { RefreshOutline } from "react-ionicons";
import { Geolocation } from "@capacitor/geolocation";
import React, { useEffect } from "react";
import { RootState } from "../app/store";
import { useDispatch, useSelector } from "react-redux";
import { useGetCurrentPositionWeatherQuery } from "../services/weather";
import { setQueryCoord } from "../app/coordQuerySlice";
import TestSkeleton from "../components/TestSkeleton";
import WeatherCard from "../components/WeatherProperty";

const Tab1: React.FC = () => {
  const dispatch = useDispatch();
  const coordQueryState = useSelector((state: RootState) => state.coordQuery);
  const {
    refetch,
    data: weatherData,
    isFetching,
    isError,
  } = useGetCurrentPositionWeatherQuery(
    {
      lat: coordQueryState.lat,
      lon: coordQueryState.lon,
      appid: "cd555b96865912ac5781d36d6d7de140",
      units: "metric",
    },
    { skip: coordQueryState.skip }
  );

  const setCurrentPosition = async () => {
    const data = await Geolocation.getCurrentPosition();
    const {
      coords: { latitude: latFetched },
      coords: { longitude: lonFetched },
    } = data;
    dispatch(setQueryCoord({ lat: latFetched, lon: lonFetched, skip: false }));
  };

  useEffect(() => {
    setCurrentPosition();
  }, []);

  function refreshCurrentPositionHandler() {
    refetch();
  }

  if (weatherData) {
    console.log(weatherData);
  }

  const weatherIconUrl = weatherData
    ? `https://openweathermap.org/img/wn/${weatherData.weather[0].icon}@2x.png`
    : undefined;
  const weatherVars = weatherData ? Object.keys(weatherData.main) : undefined;

  return (
    <IonPage>
      <IonHeader>
        <IonToolbar className={styles["ion-toolbar-dashboard"]}>
          <IonTitle className="ion-margin-bottom" size="large">
            Dashboard
          </IonTitle>
          <IonButtons slot="end">
            <IonButton>
              <RefreshOutline
                onClick={refreshCurrentPositionHandler}
                color={"black"}
                height="35px"
                width="35px"
                cssClasses={styles.refreshOutline}
              />
            </IonButton>
          </IonButtons>
        </IonToolbar>
      </IonHeader>
      <IonContent fullscreen>
        <IonGrid className="ion-no-margin">
          <IonRow style={{ margin: "10px" }}>
            <IonCol className="ion-text-center">
              <h1 style={{ fontSize: "20px" }}>
                Here's your location based weather
              </h1>
            </IonCol>
          </IonRow>
        </IonGrid>
        {!weatherData && <IonLoading isOpen={!weatherData} />}
        {isFetching && !weatherData && <IonLoading isOpen={isFetching} />}
        {isError && <IonAlert isOpen={isError} />}
        {!isFetching && weatherData && (
          <WeatherCard
            weatherIconUrl={weatherIconUrl as string} \\problem is indeed here
            weatherData={weatherData}
            weatherVars={weatherVars as string[]}
          />
        )}
      </IonContent>
    </IonPage>
  );
};

export default Tab1;

Tab2.tsx Tab2.tsx

import {
  IonContent,
  IonHeader,
  IonPage,
  IonTitle,
  IonToolbar,
} from "@ionic/react";
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { setQueryCity } from "../app/cityQuerySlice";
import { RootState } from "../app/store";
import WeatherCard from "../components/WeatherCard";
import { useGetWeatherByCityQuery } from "../services/weather";
import styles from "./Tab1.module.css";

const Tab2: React.FC = () => {
  const dispatch = useDispatch();
  const cityQueryState = useSelector((state: RootState) => state.cityQuery);
  const {
    refetch,
    data: weatherData,
    isFetching,
    isError,
  } = useGetWeatherByCityQuery(
    {
      q: cityQueryState.city,
      appid: "cd555b96865912ac5781d36d6d7de140",
      units: "metric",
    },
    { skip: cityQueryState.skip }
  );

  useEffect(() => {
    dispatch(setQueryCity({ city: "London", skip: false }));
  }, [dispatch]);

  const weatherIconUrl = weatherData
    ? `https://openweathermap.org/img/wn/${weatherData.weather[0].icon}@2x.png`
    : undefined;
  const weatherVars = weatherData ? Object.keys(weatherData.main) : undefined;

  return (
    <IonPage>
      <IonHeader>
        <IonToolbar className={styles["ion-toolbar-dashboard"]}>
          <IonTitle className="ion-margin-bottom" size="large">
            Search
          </IonTitle>
        </IonToolbar>
      </IonHeader>
      <IonContent fullscreen>
        {!weatherData && <p>weather data is loading</p>}
        {weatherData && (
          <WeatherCard
            weatherData={weatherData} \\ and here the props are passed properly...
            weatherIconUrl={weatherIconUrl as string}
            weatherVars={weatherVars as string[]}
          />
        )}
      </IonContent>
    </IonPage>
  );
};

export default Tab2;

WeatherCard.tsx天气卡.tsx

import {
  IonCard,
  IonCardContent,
  IonGrid,
  IonRow,
  IonCol,
  IonText,
} from "@ionic/react";
import { useEffect } from "react";
import WeatherProperty from "./WeatherProperty";

interface WeatherCardProps {
  weatherIconUrl: string;
  weatherVars: string[];
  weatherData: any;
}

const WeatherCard: React.FC<WeatherCardProps> = (props: WeatherCardProps) => {
  const { weatherVars, weatherData, weatherIconUrl } = props;

  console.log(weatherData);
  console.log(weatherData);
  console.log(weatherIconUrl);

  useEffect(() => {
    console.log("component WeatherCard mounted");
  });

  return (
    <IonCard>
      <IonCardContent>
        <IonGrid>
          <IonRow>
            <IonCol class="ion-text-center">
              <IonText color="primary">
                <h1 style={{ marginBottom: "0px", display: "inline" }}>
                  {weatherData.name},
                  <span style={{ color: "grey" }}>
                    {" "}
                    {weatherData.sys.country === "JP"
                      ? "Japan"
                      : "Outside Japan"}
                  </span>
                </h1>
              </IonText>
            </IonCol>
          </IonRow>
          <IonRow className="ion-justify-content-center ion-align-items-center">
            <IonCol size="auto">
              <img
                style={{
                  width: "70px",
                  height: "70px",
                  display: "inline",
                }}
                src={weatherIconUrl}
              />
            </IonCol>
            <IonCol size="auto" className="ion-justify-content-center">
              <h1
                style={{
                  display: "inline",
                  fontSize: "18px",
                }}
              >
                {weatherData.weather[0].description}
              </h1>
            </IonCol>
          </IonRow>
          <IonRow>
            <IonCol>
              <WeatherProperty
                main={weatherVars[1]}
                mainValue={weatherData.main[weatherVars[1]]}
              />
            </IonCol>
            <IonCol>
              <WeatherProperty
                main={weatherVars[2]}
                mainValue={weatherData.main[weatherVars[2]]}
              />
            </IonCol>
          </IonRow>
          <IonRow>
            <IonCol>
              <WeatherProperty
                main={weatherVars[3]}
                mainValue={weatherData.main[weatherVars[3]]}
              />
            </IonCol>
            <IonCol>
              <WeatherProperty
                main={weatherVars[5]}
                mainValue={weatherData.main[weatherVars[5]]}
              />
            </IonCol>
          </IonRow>
        </IonGrid>
      </IonCardContent>
    </IonCard>
  );
};

export default WeatherCard;

WeatherProperty.tsx WeatherProperty.tsx

import { IonItem, IonLabel, IonText, IonThumbnail } from "@ionic/react";
import { useEffect } from "react";
import "./WeatherProperty.module.css";

interface WeatherProps {
  main: string;
  mainValue: number;
}

const WeatherProperty: React.FC<WeatherProps> = (props: WeatherProps) => {
  console.log(`these are the props in WeatherProperty component`);
  console.log(props);

  let propMod;
  let unit;
  let fileName;
  if (props.main === "feels_like") {
    propMod = "It feels like:";
    unit = "deg";
    fileName = "feels-like.png";
  }
  if (props.main === "temp_min") {
    propMod = "Minimum temperature:";
    unit = "deg";
    fileName = "temp-min.png";
  }
  if (props.main === "temp_max") {
    propMod = "Maximum temperature:";
    unit = "deg";
    fileName = "temp-max.png";
  }
  if (props.main === "humidity") {
    propMod = "Humidity:";
    unit = "%";
    fileName = "humidity.png";
  }
  useEffect(() => {
    console.log("component WeatherProperty mounted");
  });

  return (
    <IonItem lines="none">
      <IonThumbnail slot="start" className="weather-icons">
        <img src={`${window.location.origin}/assets/${fileName}`} />
      </IonThumbnail>
      <IonLabel slot="">
        <IonText color="primary">
          <h1 style={{ fontSize: "15px" }}>{propMod}</h1>
        </IonText>
        <h2>{`${Math.trunc(props.mainValue)} ${unit}`}</h2>
      </IonLabel>
    </IonItem>
  );
};

export default WeatherProperty;

There are two things you need to fix:您需要修复两件事:

  1. Imported from the wrong component从错误的组件导入

Tab1.tsx Tab1.tsx

import WeatherCard from "../components/WeatherProperty";

// Maybe the correct one is "WeatherCard" ?
// import WeatherCard from "../components/WeatherCard";
  1. Assigned the wrong type definition for props为道具分配了错误的类型定义

WeatherCard.tsx天气卡.tsx

const WeatherProperty: React.FC<WeatherProps> = (props: WeatherProps) => {

// you can just omit the prop's type 
// (props) => { 
// 
// or use object destructuring for the convenience
// ({ weatherData, weatherVar, weatherIconUrl }) => {

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 打字稿React.FC<Props> 困惑 - TypeScript React.FC<Props> confusion 如何使用 React.FC<props> 当子节点可以是 React 节点或函数时键入 - How to use React.FC<props> type when the children can either be a React node or a function 反应-传递道具,导航器中的设置错误? - React - passing props, wrong setup in navigator? 反应-在道具变更时重新渲染是否错误? - React - is it wrong to rerender on props change? 将引用转发到 react.FC 给出类型错误:属性引用不存在于类型 &#39;IntrinsicAttributes &amp; Props &amp; { children :? 反应节点} - forwarding ref to react.FC gives type error: Property ref does not exist on type 'IntrinsicAttributes & Props & { children :? ReactNode} React + TypeScript:将React组件作为道具传递,使用道具进行渲染[错误:TS2339] - React + TypeScript: Passing React Component as Props, rendering with props [Error: TS2339] 在 React Typescript 中发送道具 - Sending props in React Typescript 道具传播与 typescript 反应 - Props spread in react with typescript 使用钩子将打字稿传递函数作为道具进行反应 - React with typescript passing function as props using hooks 将道具传递给 Typescript 中的功能性 React 组件 - Passing props to functional React component in Typescript
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM