React-Query useQuery 发送无限获取请求

React-Query useQuery sending infinite fetch requests

当我像下面那样使用 useQuery 时,按照它在 react-query 文档中的使用方式,它会发送无限数量的提取请求。文档还说 fetch 不会自动抛出错误。因此,我在下面尝试了相同的代码,但 getAlbums 使用了 try-catch 块。我还尝试在 useQuery 挂钩的对象中配置 staleTime,但它没有用,我什至不知道什么是过时时间。哈哈。请帮帮我。努力在星期一之前完成这个项目

在我的控制台中发现了这个错误:

(node:27609) UnhandledPromiseRejectionWarning: ReferenceError: navigator is not defined
    at OnlineManager.isOnline (/Users/benridesbikes/repos/photo_album/node_modules/react-query/lib/core/onlineManager.js:64:5)
    at /Users/benridesbikes/repos/photo_album/node_modules/react-query/lib/core/retryer.js:142:86
(Use `node --trace-warnings ...` to show where the warning was created)
(node:27609) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 3)
(node:27609) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
import React from "react";
import { useQuery, useMutation, useQueryClient } from "react-query";
import Link from "next/link";
import Form from "../../components/styles/Form";
import Container from "../../components/styles/AlbumsIndex";
import Button from "../../components/styles/Button";

async function getAlbums() {
  const response = await fetch(`api/albums/`);
  const { albums } = await response.json();
  return albums;
}

async function createAlbum(newAlbum) {
  const response = await fetch(`/api/albums/create`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(newAlbum),
  });
  const { album } = await response.json();
  return album;
}

async function deleteAlbum(albumId) {
  await fetch(`/api/albums/delete`, {
    method: "DELETE",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(albumId),
  });
}

export default function Index() {
  const queryClient = useQueryClient();

  const refetchQuery = async () => {
    await queryClient.refetchQueries();
  };

  const { data: albums, error } = useQuery("albums", getAlbums);

  const mutationCreateAlbum = useMutation(createAlbum, {
    onSuccess: refetchQuery(),
  });

  const mutationDeleteAlbum = useMutation(deleteAlbum, {
    onSuccess: refetchQuery(),
  });

  const [formData, setFormData] = React.useState({
    name: "",
    description: "",
  });

  const handleChange = (event) => {
    setFormData({ ...formData, [event.target.name]: event.target.value });
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    mutationCreateAlbum.mutate({
      name: formData.name,
      description: formData.description,
    });
    setFormData({
      name: "",
      description: "",
    });
  };

  const useDeleteMutation = (albumId) => {
    mutationDeleteAlbum.mutate({
      id: albumId,
    });
  };

  return (
    <Container>
      <Form>
        <h1>Create a New Album</h1>
        <label htmlFor="name">
          Name:
          <input
            type="text"
            id="name"
            name="name"
            value={formData.name}
            onChange={handleChange}
            placeholder="Give Your Album a Name!"
          />
        </label>
        <label htmlFor="description">
          Description:
          <input
            type="text"
            id="description"
            name="description"
            value={formData.description}
            onChange={handleChange}
            placeholder="Give Your Album a Description!"
          />
        </label>
        <Button onClick={(event) => handleSubmit(event)}>
          Make New Album!
        </Button>
      </Form>
      <div className="albums">
        {albums &&
          albums.map((album) => (
            <div className="album" key={album.id}>
              <Link href={`/albums/${album.id}`}>
                <a>
                  <Button>{album.name}</Button>
                </a>
              </Link>
              <h3>{album.description}</h3>
              <Button onClick={() => useDeleteMutation(album.id)}>
                Delete
              </Button>
            </div>
          ))}
      </div>
    </Container>
  );
}

已解决! IDK 正是为什么 这个解决方案有效。我有一种预感,它与钩子和 React 重新渲染有关。简而言之函数:

 const refetchQuery = async () => {
    await queryClient.refetchQueries();
  };

是不断发送抓取的原因。解决方案是删除这个函数,在 onSuccess 之后调用 'queryClient.refetchQueries()' 作为异步函数,像这样:

  const queryClient = useQueryClient();

  const { data: albums, error } = useQuery("albums", getAlbums);

  const mutationCreateAlbum = useMutation(createAlbum, {
    onSuccess: async () => await queryClient.refetchQueries(),
  });

  const mutationDeleteAlbum = useMutation(deleteAlbum, {
    onSuccess: async () => await queryClient.refetchQueries(),
  });

问题似乎是您在声明突变时调用了 refetchQuery 函数:

  const mutationCreateAlbum = useMutation(createAlbum, {
    onSuccess: refetchQuery(),
  });

refetchQuery() 是直接函数调用。你想要的是:

  const mutationCreateAlbum = useMutation(createAlbum, {
    onSuccess: refetchQuery,
  });

注意缺少调用括号,所以我们只是传递函数,而不是调用它。或者:

  const mutationCreateAlbum = useMutation(createAlbum, {
    onSuccess: () => refetchQuery(),
  });

声明一个新的内联函数然后调用 refetchQuery.