【问题标题】:NextJs app using JavaScript toISOString() in SWR causing infinite API callsNextJs 应用在 SWR 中使用 JavaScript toISOString() 导致无限 API 调用
【发布时间】:2021-08-18 21:31:27
【问题描述】:

我设置了以下示例 Next.js 应用程序来测试我在对 API 端点的 useSWR 调用中包含的变量使用 toISOString() JavaScript 函数时看到的问题:

下面是pages/user/[id].tsx 的代码,其中toISOString() 被调用:

import NextLink from "next/link";
import {
  Link,
  Flex,
  Box,
  Text,
  SimpleGrid,
  Heading,
  Alert
} from "@chakra-ui/core";
import useSWR from "swr";
import { useRouter } from "next/router";
type Data = {
  id: string;
  name: string;
  email: string;
};

const fetcher = async (url: string) => {
  const res = await fetch(url);
  if (!res.ok) {
    throw Error("Yo that's NOT OK!!!");
  }
  const data: Data = await res.json();
  return data;
};

const UserData = () => {
  const router = useRouter();
  const { id } = router.query;
  const today = new Date();
  const yesterday = new Date(today);
  yesterday.setDate(yesterday.getDate() - 1);
  const ssd = yesterday.toISOString(); // TROUBLE
  // const ssd = "2021-08-16T19:27:51.630Z"; //fine

  const result = useSWR(`/api/user/${id}/${ssd}`, fetcher, {
    revalidateOnFocus: false
  });
  const data: Data = result.data;
  const error: Error = result.error;

  if (error) {
    return <Alert status="error">Loading failed: {error.message}</Alert>;
  }

  if (!data) {
    return <Alert status="info">Loading...</Alert>;
  }

  return (
    <SimpleGrid columns={2} width="2xs" spacingY={4}>
      <Text fontWeight="bold" marginRight={4}>
        UserID
      </Text>
      <Text>{data.id}</Text>

      <Text fontWeight="bold" marginRight={4}>
        Name
      </Text>
      <Text>{data.name}</Text>

      <Text fontWeight="bold" marginRight={4}>
        Email
      </Text>
      <Text>{data.email}</Text>
    </SimpleGrid>
  );
};

const UserPage = () => {
  return (
    <Box>
      <Flex flexDirection="column" alignItems="center">
        <Heading marginY="2rem">User</Heading>
        <UserData />
        <NextLink href="/">
          <Link marginY="2rem">
            <Text fontStyle="italic">Go back home</Text>
          </Link>
        </NextLink>
      </Flex>
    </Box>
  );
};

export default UserPage;

pages/user/[id].tsx 的第 34 行是调用 toISOString() 并触发多个 API 调用的位置,如浏览器控制台所示(控制台语句添加到 /pages/api/user/[...params].ts 第 7 行 - 请参阅下面的完整示例代码)。 toISOString() 函数似乎就像 Next.js 中的 useState 函数一样,因此触发了似乎不会停止的 API 调用。

关于如何使用toISOString() 并且不让它通过useSWR() 触发多个API 调用的任何想法?

以下是完整示例应用的副本:

https://codesandbox.io/s/consume-next-js-api-routes-with-the-swr-library-on-the-client-side-forked-mzgwz?file=/pages/user/%5Bid%5D.tsx

【问题讨论】:

  • 请包含所涉及代码的minimal reproducible example,而不是让人们来回访问您的代码框,如果他们甚至可以访问它。见How to Ask
  • @w-patrick-gale,请查看答案,如果它解决了您的问题,请告诉我们
  • 感谢@AppCity 的回答。 HM,我在问题中嵌入了示例代码(谢谢,如果我应该包含更多内容,请告诉我)。我仍然不明白为什么 ISOString 函数需要在运行 SWR 的函数之外。在我的生产代码中,我在主导出函数中有 ISOString 函数和 SWR 代码。当我将 SWR 代码从主导出函数中移出并放入一个单独的函数(例如答案中的 UserData)并传入 ISOString 值时,这解决了无限 API 调用。但是为什么首先要进行无限的 API 调用呢?

标签: reactjs next.js swr


【解决方案1】:

这是解决无限 API 调用问题的更新代码,只需将 ISOString 移至父级即可。

import NextLink from "next/link";
import {
  Link,
  Flex,
  Box,
  Text,
  SimpleGrid,
  Heading,
  Alert
} from "@chakra-ui/core";
import useSWR from "swr";
import { useRouter } from "next/router";
type Data = {
  id: string;
  name: string;
  email: string;
};

const fetcher = async (url: string) => {
  const res = await fetch(url);
  if (!res.ok) {
    throw Error("Yo that's NOT OK!!!");
  }
  const data: Data = await res.json();
  return data;
};

const UserData = ({ ssd }) => {
  const router = useRouter();
  const { id } = router.query;

  // const ssd = "2021-08-16T19:27:51.630Z"; //fine

  const result = useSWR(`/api/user/${id}/${ssd}`, fetcher, {
    revalidateOnFocus: false
  });
  const data: Data = result.data;
  const error: Error = result.error;

  if (error) {
    return <Alert status="error">Loading failed: {error.message}</Alert>;
  }

  if (!data) {
    return <Alert status="info">Loading...</Alert>;
  }

  return (
    <SimpleGrid columns={2} width="2xs" spacingY={4}>
      <Text fontWeight="bold" marginRight={4}>
        UserID
      </Text>
      <Text>{data.id}</Text>

      <Text fontWeight="bold" marginRight={4}>
        Name
      </Text>
      <Text>{data.name}</Text>

      <Text fontWeight="bold" marginRight={4}>
        Email
      </Text>
      <Text>{data.email}</Text>
    </SimpleGrid>
  );
};

const UserPage = () => {
  const today = new Date();
  const yesterday = new Date(today);
  yesterday.setDate(yesterday.getDate() - 1);
  const ssd = yesterday.toISOString(); // No More TROUBLE

  return (
    <Box>
      <Flex flexDirection="column" alignItems="center">
        <Heading marginY="2rem">User</Heading>
        <UserData ssd={ssd} />
        <NextLink href="/">
          <Link marginY="2rem">
            <Text fontStyle="italic">Go back home</Text>
          </Link>
        </NextLink>
      </Flex>
    </Box>
  );
};

export default UserPage;

【讨论】:

    猜你喜欢
    • 2021-06-12
    • 2020-09-17
    • 2021-03-29
    • 2020-10-27
    • 2021-12-14
    • 2021-09-08
    • 1970-01-01
    • 2011-08-23
    • 1970-01-01
    相关资源
    最近更新 更多