0

当我使用下面的 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>
  );
}
4

2 回答 2

1

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

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

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

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

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

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

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

于 2020-12-30T08:44:46.840 回答
0

解决了!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(),
  });
于 2020-12-27T00:44:25.380 回答