skip to Main Content

If I switch too fast in 5 seconds on mobile chrome, useEffect will not fetch data from openWeatherAPI.
But wait it for 5 second and reswitch page, it is ok to fetch and display.

My weather app by Next.js app route deploy on vercel has two pages "/", "/week".
I use getPosition() get lat and lon, fetchApi() get weather data, and <Link> to switch pages.

homePage("/")

"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;

pageSwitch in Layout

"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;

I think the problem is useEffect dependencies([]), maybe <Link> to page not means the initial render?

I try to link my phone to desktop with USB debug to see real mobile chrome devTool Network page.

mobile devTool-Network page

And compare with desktop devTool-Network page.

desktop devTool-Network page

I just hope it normally fetch data on android like desktop.
Please give me some advice, thanks!

2

Answers


  1. After checking your code, just like you said about "useEffect dependencies([])".

    In both of components, you’re using an empty dependency array ([]) for useEffect, which means the effect will only run once after the initial render.

    So if the component is unmounted and remounted quickly due to your rapid page switches, useEffect won’t run again unless its dependencies change.

    Also consider include position as a dependency to trigger useEffect when the geolocation changes.

    Login or Signup to reply.
  2. have you tried disabling next caching in your fetch request?

    fetch('https://...', { next: { revalidate: 0} })
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search