0

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

以下是调用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;

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

关于如何使用toISOString()而不是让它触发多个 API 调用的任何想法useSWR()

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

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

4

1 回答 1

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-08-19T05:11:42.953 回答