Статус = успешно, несмотря на то, что мои изображения не полностью загружены из API в react-query3

#reactjs #react-query

Вопрос:

Я учусь использовать react-запрос, извлекая изображения из unsplash API.

Я хочу установить счетчик, пока мои изображения извлекаются, но статус установлен на успех еще до того, как мои изображения будут полностью загружены на страницу (я проверил с помощью console.log(статус))

Это то, что у меня есть:

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" amp;amp; (
        <Spinner animation="border" role="status">
          <span className="visually-hidden">Loading...</span>
        </Spinner>
      )}

      {status === "error" amp;amp; <div>Error</div>}

      {status === "success" amp;amp; 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;
 

Я не знаю, как лучше всего достичь того, что мне нужно. В принципе, я хочу, чтобы только один счетчик, который появится в середине страницы и отобразит мои дивы, как только все изображения будут полностью загружены, как это, пользователь не увидит, как загружаются изображения на его странице.

Ответ №1:

вы создаете new QueryClient внутри своего App — так что каждый раз, когда он повторно отображается, например , из-за вашего вызова setPage , вы будете получать новый клиент запроса, что также означает новый кэш.

Клиент запроса должен быть стабильным, либо созданным вне приложения, либо с помощью константы типа:

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

Комментарии:

1. Благодаря вам, так что мне удалось это сделать (я опубликовал ответ). Не могли бы вы просто дать мне знать, что означает [0] ? А как насчет того, чтобы у меня было несколько вызовов api на одной странице ? (извините, с сегодняшнего дня я учусь реагировать на запросы)

2. useState возвращает массив с двумя элементами, поэтому мы берем первый элемент из него с помощью [0]

Ответ №2:

Спасибо за ответ ниже. Мне удалось сделать это так:

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" amp;amp; <div>Error</div>}

      {status === "success" amp;amp; 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 amp;amp; (
        <>
          <Spinner animation="border" role="status">
            <span className="visually-hidden">Loading...</span>
          </Spinner>
        </>
      )}
    </div>
  );
};

export default Image;