为什么 useEffect fetch 在移动设备上不起作用,但在桌面上起作用?

问题描述 投票:0回答:1

如果我在移动 chrome 上 5 秒内切换得太快,useEffect 将无法从 openWeatherAPI 获取数据。 但等5秒,重新切换页面,就可以读取并显示了。

我的天气应用程序由 Next.js 应用程序路由部署在 vercel 上,有两个页面“/”、“/week”。 我使用 getPosition() 获取纬度和经度,使用 fetchApi() 获取天气数据,并使用 切换页面。

主页(“/”)

"use client";

import { fetchApi } from "@/api/fetchApi";
import InfoBox from "@/components/InfoBox";
import RainChart from "@/components/RainChart";
import TempChart from "@/components/TempChart";
import { getPosition } from "@/utils/getPosition";
import { unixToDate } from "@/utils/unixToDate";
import { unixToTime } from "@/utils/unixToTime";
import { useEffect, useState } from "react";

export default function Home() {
  const [date, setDate] = useState<string>("");
  const [time, setTime] = useState<string>("");
  const [desc, setDesc] = useState<string>("");
  const [feel, setFeel] = useState<number>(0);
  const [hourFeel, setHourFeel] = useState<number[]>([]);
  const [hourRain, setHourRain] = useState<number[]>([]);

  useEffect(() => {
    getPosition()
      .then((position) => {
        fetchApi(position.coords.latitude, position.coords.longitude, "metric")
          .then((data: any) => {
            setTime(unixToTime(data.current.dt));
            setDate(unixToDate(data.current.dt));
            setDesc(data.current.weather[0].description);
            setFeel(Math.round(data.current.feels_like));

            const hourFeelData: number[] = [];
            const hourRainData: number[] = [];

            for (let i = 0; i < 24; i++) {
              hourFeelData.push(Math.round(data.hourly[i].feels_like));
              setHourFeel(hourFeelData);

              hourRainData.push(Math.round(data.hourly[i].pop * 100));
              setHourRain(hourRainData);
            }
          })
          .catch((err) => {
            console.error(err);
          });
      })
      .catch((err) => {
        console.log(err);
      });
  }, []);

  return (
    <main>
      <div className="mt-5 flex justify-evenly">
        <InfoBox date={date} time={time} content={desc} />
        <InfoBox label="現在體感" content={`${feel}℃`} />
      </div>
      <TempChart data={hourFeel} />
      <RainChart data={hourRain} />
    </main>
  );
}

weekPage(“/week”)

"use client";

import { fetchApi } from "@/api/fetchApi";
import { getPosition } from "@/utils/getPosition";
import { unixToDate } from "@/utils/unixToDate";
import { useEffect, useState } from "react";
import DaysDetails from "@/components/DaysDetails";

const WeekPage = () => {
  const loop = [];
  for (let i = 0; i < 8; i++) {
    loop.push(i);
  }

  const [date, setDate] = useState<string[]>(["", "", "", "", "", "", "", ""]);
  const [desc, setDesc] = useState<string[]>(["", "", "", "", "", "", "", ""]);
  const [dayFeel, setDayFeel] = useState<number[]>([0, 0, 0, 0, 0, 0, 0, 0]);
  const [eveFeel, setEveFeel] = useState<number[]>([0, 0, 0, 0, 0, 0, 0, 0]);
  const [rain, setRain] = useState<number[]>([0, 0, 0, 0, 0, 0, 0, 0]);

  useEffect(() => {
    getPosition()
      .then((position) => {
        fetchApi(position.coords.latitude, position.coords.longitude, "metric")
          .then((data: any) => {
            const dateData: string[] = [];
            const descData: string[] = [];
            const rainData: number[] = [];
            const eveFeelData: number[] = [];
            const dayFeelData: number[] = [];

            for (let i = 0; i < 8; i++) {
              dateData.push(unixToDate(data.daily[i].dt));
              setDate(dateData);

              descData.push(data.daily[i].weather[0].description);
              setDesc(descData);

              dayFeelData.push(Math.round(data.daily[i].feels_like.day));
              setDayFeel(dayFeelData);

              eveFeelData.push(Math.round(data.daily[i].feels_like.eve));
              setEveFeel(eveFeelData);

              rainData.push(Math.round(data.daily[i].pop * 100));
              setRain(rainData);
            }
          })
          .catch((err) => {
            console.error(err);
          });
      })
      .catch((err) => {
        console.log(err);
      });
  }, []);

  return (
    <div className="flex h-[43.75rem] flex-col items-center justify-evenly">
      {loop.map((i) => (
        <DaysDetails
          key={i}
          date={date[i]}
          desc={desc[i]}
          rain={`${rain[i]}%`}
          dayFeel={`${dayFeel[i]}℃`}
          eveFeel={`${eveFeel[i]}℃`}
        />
      ))}
    </div>
  );
};

export default WeekPage;

布局中的页面切换

"use client";

import Link from "next/link";
import { useState } from "react";

const PageSwitcher: React.FC = () => {
  const [page, setPage] = useState("now");

  return (
    <div className="flex justify-center">
      <Link
        href="/"
        onClick={() => setPage("now")}
        className={`flex h-14 w-[11.5rem] items-center justify-center ${page === "now" ? "bg-slate-300" : "bg-inherit"}`}
      >
        NOW
      </Link>
      <Link
        href="/week"
        onClick={() => setPage("7days")}
        className={`flex h-14 w-[11.5rem] items-center justify-center ${page === "7days" ? "bg-slate-300" : "bg-inherit"}`}
      >
        7 DAYS
      </Link>
    </div>
  );
};

export default PageSwitcher;

我认为问题是useEffect依赖项([]),也许到页面并不意味着初始渲染?

我尝试使用 USB 调试将我的手机链接到桌面,以查看真实的移动 chrome devTool 网络页面。

移动开发工具-网络页面

并与桌面devTool-Network页面进行比较。

桌面开发工具-网络页面

我只是希望它能像台式机一样在 Android 上正常获取数据。 请给我一些建议,谢谢!

javascript
1个回答
0
投票

检查代码后,就像您所说的“useEffect依赖项([])”。

在这两个组件中,您都为 useEffect 使用空依赖数组 ([]),这意味着效果只会在初始渲染后运行一次。

因此,如果由于快速页面切换而快速卸载并重新挂载组件,则 useEffect 将不会再次运行,除非其依赖项发生变化。

还可以考虑将位置包含为依赖项,以便在地理位置发生变化时触发 useEffect。

© www.soinside.com 2019 - 2024. All rights reserved.