开发者问题收集

找不到我的应用返回 Uncaught TypeError: Cannot read properties of undefined 的原因

2023-04-14
96

我正在使用 useState 来存储从 api 返回的数据:

function App() {
  const [{ ipAddressData, shouldLoadItems }, setModel] = useState<AppState>({
    ipAddressData: [],
    shouldLoadItems: true,
  });
  const [ipAddress, setIpAddress] = useState("");
  const ipDataUrl = `https://geo.ipify.org/${ipAddress}`;

  useEffect(() => {
    const fetchData = async () => {
      const response = await fetch(ipDataUrl);
      const data: IpAddress[] = await response.json();
      setModel({
        ipAddressData: data,
        shouldLoadItems: false,
      });
    };
    if (shouldLoadItems) {
      fetchData();
    }
  }, [shouldLoadItems]);


  function inputIp(e: { preventDefault: () => void }) {
    setModel((prevState) => {
      return {
        ...prevState,
        shouldLoadItems: true,
      };
    });
    e.preventDefault();
  }

然后我尝试返回数据,但出现以下错误: Uncaught TypeError:无法读取未定义的属性

const { ip, location, domains, as, isp }: IpAddressData = ipAddressData;

  return (
    <div className="App">
      <main className={mainCss}>
        <h1 className={mainTitleCss}>IP Address Tracker</h1>
        <form className={searchBarContainerCss} onSubmit={inputIp}>
          <input
            type="text"
            placeholder="Search for any IP address or domain"
            className={searchInputCss}
            onChange={(e) => setIpAddress(e.target.value)}
          />
          <input type="submit" value="" className={searchBarButtonCss} />
        </form>
        <Results
          ip={ip}
          location={getLocation(
            location.city,
            location.country,
            location.postalCode
          )}
          timezone={location.timezone}
          isp={isp}
        />

function getLocation(city: string, country: string, postalCode: string) {
  return `${city}, ${country} ${postalCode}`;
}

Results.tsx:

interface IpAddressProps {
  ip: string;
  location: string;
  timezone: string;
  isp: string;
}

const Results: FC<IpAddressProps> = ({ ip, location, timezone, isp }) => {
  return (
    <div className={resultsContainerCss}>
      <div className={resultCss}>
        <div className={resultTitleCss}>IP Address</div>
        <div className={resultInfoCss}>{ip}</div>
      </div>
      <div className={resultCss}>
        <div className={resultTitleCss}>Location</div>
        <div className={resultInfoCss}>{location}</div>
      </div>
      <div className={resultCss}>
        <div className={resultTitleCss}>Timezone</div>
        <div className={resultInfoCss}>UTC {timezone}</div>
      </div>
      <div className={resultCss}>
        <div className={resultTitleCss}>ISP</div>
        <div className={resultInfoCss}>{isp}</div>
      </div>
    </div>
  );
};

export default Results;

存储我的接口的 index.ts:

interface Location {
  country: string;
  region: string;
  city: string;
  lat: number;
  lng: number;
  postalCode: string;
  timezone: string;
  geonameId: number;
}
interface As {
  asn: number;
  name: string;
  route: string;
  domain: string;
  type: string;
}

export interface IpAddressData {
  ip: string;
  location: Location;
  domains: string[];
  as: As;
  isp: string;
}

export interface IpAddress {
  data: IpAddressData;
}

当我 console.log ipAddressData 时,它会按预期从 api 返回数据,所以我不知道问题是什么

2个回答

首先,这两段代码是相互冲突的。

const [{ ipAddressData, shouldLoadItems }, setModel] = useState<AppState>({
    ipAddressData: [],
    shouldLoadItems: true,
});
setModel({
    ipAddressData: data,
    shouldLoadItems: false,
});

您的 useState 数组中有一个名为 ipAddressData 的变量, setModel 中也有一个名为 ipAddressData 的变量。如果您将鼠标悬停在 setModel 调用中的 ipAddressData 上。它会说 ipAddressData 不可分配。

我建议将 useState 返回的第一个变量名称更改为如下所示:

const [data, setModel] = useState<AppState>({
    ipAddressData: [],
    shouldLoadItems: true,
  });

这样当您调用时:

setModel({
    ipAddressData: data,
    shouldLoadItems: false,
});

它不是说 ipAddressData 不可分配。

稍后,如果您想引用 ipAddressDatashouldLoadItems 值。您可以像 data.ipAddressDatadata.shouldLoadItems 那样调用它。

之后,看看您的错误 Uncaught TypeError 是否消失。

Khairani F
2023-04-14

我发现错误, AppState 接口将 ipAddressData 定义为一个数组,而实际上它应该是一个对象,这就是它返回未定义的原因。

interface AppState {
  ipAddressData: IpAddressData[];
  shouldLoadItems: boolean;
}

应该是这个:

interface AppState {
  ipAddress: IpAddress | undefined;
  shouldLoadItems: boolean;
}
Alex
2023-04-14