DEV Community

sundaycoding
sundaycoding

Posted on

React Query: как я упростил управление серверным состоянием в React

React Query: как я упростил управление серверным состоянием в React
Обработка данных, которые приходят с сервера, может стать настоящей головной болью в React. Нужно думать о многом: обновление, кэширование, повторная загрузка... React Query здорово мне в этом помогает! Он берет на себя все эти сложности, а еще предлагает простые решения для оптимистичного рендеринга, бесконечного скролла, пагинации и многого другого.

Хочу поделиться своим опытом использования React Query и показать, как он упрощает разработку.

Установка и подготовка
Для начала, я создал новое React-приложение с помощью npx create-react-app. Затем установил React Query с помощью npm i --save react-query.

Для демонстрации я использовал Json Placeholder API, чтобы создать простой блог.

Загрузка данных
Сначала я удалил весь шаблонный код в App.js и заменил его следующим кодом:

JavaScript

import React from 'react';
import { useQuery } from 'react-query';

const getPosts = async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
return response.json();
};

function App() {
const { status, data, isFetching, error } = useQuery('posts', getPosts);

if (status === 'loading') {
return

Загрузка...; // loading state
}

if (status === 'error') {
return

Ошибка: {error.message}; // error state
}

return (


{data && (
    {data .slice(0, 10) // только первые 10 .map((d) => (
  • {d.title}
  • ))}

)}
{isFetching &&

Обновление...

}

);
}

export default App;
Сначала я определил функцию getPosts — она может включать в себя что угодно, главное, чтобы она возвращала асинхронную функцию.

Внутри компонента App я вызвал хук useQuery с идентификатором для данных ('posts') и асинхронной функцией getPosts.

Хук возвращает status, data, isFetching и error. status может быть 'success', 'loading' или 'error'. Остальная часть компонента отображает результат в трех возможных состояниях.

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

Это, в принципе, все, что вам нужно знать, чтобы начать использовать React Query. Но давайте расширим этот пример, чтобы увидеть кэширование и обновление в действии!

Расширение приложения
Сначала я перенес код из App.js в новый компонент components/Home.js. Далее я переименую компонент и добавлю NavLink в список сообщений.

JavaScript

import React from 'react';
import { NavLink } from 'react-router-dom';
import { useQuery } from 'react-query';

const getPosts = async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
await new Promise((r) => setTimeout(r, 1000)); // wait a second
return response.json();
};

function Home() {
const { status, data, isFetching, error } = useQuery('posts', getPosts);

if (status === 'loading') {
return

Загрузка...; // loading state
}

if (status === 'error') {
return

Ошибка: {error.message}; // error state
}

return (


{data && (
    {data .slice(0, 10) // только первые 10 .map((d) => (
  • {d.title}
  • ))}

)}
{isFetching &&

Обновление...

}

);
}

export default Home;
Теперь добавим в App.js маршрутизатор, который сопоставляет маршруты / для Home.js и /post/:id для страницы отдельного поста.

JavaScript

import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Home from './components/Home';
import Post from './components/Post';

function App() {
return (



path="/post/:id"
render={(routerProps) => }
/>


);
}

export default App;
И наконец, я создал новый компонент components/Post.js для отображения данных одного поста.

JavaScript

import React from 'react';
import { NavLink } from 'react-router-dom';
import { useQuery } from 'react-query';

const Post = ({ id }) => {
const getPost = async () => {
const response = await fetch(https://jsonplaceholder.typicode.com/posts/${id});
const jsonResponse = await response.json();
jsonResponse.title = ${jsonResponse.title} - ${Math.random().toString(36)};

await new Promise((r) => setTimeout(r, 1000)); // wait a second
return jsonResponse;
Enter fullscreen mode Exit fullscreen mode

};

const { status, data, isFetching } = useQuery(post-${id}, getPost);

if (status === 'loading') {
return

Загрузка...; // loading state
}

return (


{data.title}


{data.body}


{isFetching &&

Обновление...

}


Домой

);
};

export default Post;
Здесь useQuery не сильно отличается от того, что в Home.js. Он добавляет id к идентификатору, поэтому каждое сообщение имеет свой собственный state. Кроме того, я добавил тайм-аут в 1 секунду к функции getPost, чтобы сделать состояние загрузки более заметным. Также я добавил случайную строку к заголовку, чтобы сделать повторную загрузку видимой.

И это, на самом деле, весь код, который вы видели в начале поста.

Если вы начнете работать с React Query, я бы порекомендовал вам посмотреть react-query-devtools, чтобы иметь возможность просматривать state и кэш.

Top comments (0)