Status = success 尽管我的图像没有从 API 在 react-query 3 中完全加载

Status = success dispite my images are not full loaded from API in react-query3

我正在学习如何通过从 unsplash 获取图像来使用 react-query API。

我想在获取图片时设置一个微调器,但状态甚至在我的图片完全加载到页面之前就已设置为成功(我已经使用 console.log(status) 进行了检查)

这是我的:

App.js

import React, { useState } from "react";
import { QueryClient, QueryClientProvider } from "react-query";
import { ReactQueryDevtools } from "react-query/devtools";
import GetImages from "./components/GetImages";
import NavBar from "./components/NavBar";
import PostImage from "./components/PostImage";

function App() {
  const queryClient = new QueryClient();
  const [page, setPage] = useState("get");

  return (
    <>
      <QueryClientProvider client={queryClient}>
        <div className="App">
          <NavBar setPage={setPage} />
          <div>{page === "get" ? <GetImages /> : <PostImage />}</div>
        </div>
        <ReactQueryDevtools initialIsOpen={false} />
      </QueryClientProvider>
    </>
  );
}

export default App;

GetImages.js

import React from "react";
import { useQuery } from "react-query";
import Image from "./Image";
import Spinner from "react-bootstrap/Spinner";

const fetchImage = async () => {
  let config = {
    method: "GET",
    headers: {
      Authorization: "Client-ID ID",
    },
    mode: "cors",
    cache: "default",
  };
  const res = await fetch("https://api.unsplash.com/photos", config);
  return res.json();
};

const GetImages = () => {
  const { data, status } = useQuery("images", fetchImage);

  return (
    <div>
      {status === "loading" && (
        <Spinner animation="border" role="status">
          <span className="visually-hidden">Loading...</span>
        </Spinner>
      )}

      {status === "error" && <div>Error</div>}

      {status === "success" && data.map((image) => <Image key={image.id} image={image} />)}
    </div>
  );
};

export default GetImages;

Image.js

const Image = ({ image }) => {
  return (
    <div className="card">
      <img src={image.urls.raw} alt={image.alt_description} style={{ width: 100, height: "auto" }} />
    </div>
  );
};

export default Image;

我不知道实现我需要的最好方法是什么。基本上我只想要一个出现在页面中间的微调器,并在所有图像都完全加载后显示我的 div,这样用户将看不到图像加载到其页面上。

您正在创建 new QueryClient inside 您的 App - 因此每次重新呈现时,例如,因为您调用 setPage,你会得到一个新的QueryClient,也就是一个新的Cache。

QueryClient 必须是稳定的,可以在 App 外部创建,也可以使用如下常量创建:

const queryClient = useState(() => new QueryClient())[0]

感谢下面的回答。我设法做到了:

App.js

import React, { useState } from "react";
import { QueryClient, QueryClientProvider } from "react-query";
import { ReactQueryDevtools } from "react-query/devtools";
import GetImages from "./components/GetImages";
import NavBar from "./components/NavBar";
import PostImage from "./components/PostImage";

function App() {
  const queryClient = useState(() => new QueryClient())[0];
  const [page, setPage] = useState("get");

  return (
    <>
      <QueryClientProvider client={queryClient}>
        <div className="App">
          <NavBar setPage={setPage} />
          <div>{page === "get" ? <GetImages /> : <PostImage />}</div>
        </div>
        <ReactQueryDevtools initialIsOpen={false} />
      </QueryClientProvider>
    </>
  );
}

GetImages.js

import React from "react";
import { useQuery } from "react-query";
import Image from "./Image";

const fetchImage = async () => {
  let config = {
    method: "GET",
    headers: {
      Authorization: "Client-ID ID    },
    mode: "cors",
    cache: "default",
  };
  const res = await fetch("https://api.unsplash.com/photos", config);
  return res.json();
};

const GetImages = () => {
  const { data, status } = useQuery("images", fetchImage);

  return (
    <div>
      {status === "error" && <div>Error</div>}

      {status === "success" && data.map((image) => <Image key={image.id} image={image} />)}
    </div>
  );
};

export default GetImages;

Images.js

import React, { useState } from "react";
import "bootstrap/dist/css/bootstrap.css";
import Spinner from "react-bootstrap/Spinner";

const Image = ({ image }) => {
  const [load, setLoad] = useState(false);
  return (
    <div className="card">
      <img
        src={image.urls.raw}
        alt={image.alt_description}
        style={load ? { width: 100, height: "auto" } : { display: "none" }}
        onLoad={() => setLoad(true)}
      />
      {!load && (
        <>
          <Spinner animation="border" role="status">
            <span className="visually-hidden">Loading...</span>
          </Spinner>
        </>
      )}
    </div>
  );
};

export default Image;