#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;