Изучение того, как выполнять вызовы API, имеет решающее значение, поскольку большинство приложений взаимодействуют с бэкендом для отображения информации, выполнения аутентификации, проверки подлинности и т.д. Одним из наиболее используемых способов сделать это является Axios.
Что такое Axios?
Axios – это клиентская библиотека HTTP на основе обещаний для nodejs и браузера, использующая API типа XMLHttpRequest из браузера и http из nodejs.
К его преимуществам относятся:
- Простота работы с JSON (меньше кода).
- Функции, соответствующие методам HTTP (get, post, delete …).
- Может использоваться как на клиенте, так и на сервере.
Установка
Если у вас есть существующий проект React, вам просто нужно установить Axios с помощью npm (или любого другого менеджера пакетов):
npm install axios
Давайте выполним примеры использования axios вместе с JSON Placeholder API для получения и изменения данных поста.
Выполнение GET-запросов
Чтобы сделать запрос ресурса к серверу, мы используем метод HTTP GET, здесь мы рассмотрим простой пример.
import React, { useEffect, useState } from "react";
import axios from "axios";
const baseUrl = "https://jsonplaceholder.typicode.com/posts";
export function Post() {
const [post, setPost] = useState(null);
useEffect(() => {
axios.get(`${baseUrl}/1`).then(({ data }) => setPost(data));
}, []);
if (!post) return null;
return (
<div>
<h2>{post.title}</h2>
<p>{post.body}</p>
</div>
);
};
Мы используем хуки useState для хранения возврата API и useEffect, который мы используем для выполнения вызова после сборки пользовательского интерфейса, затем мы используем метод GET импорта Axios в начале файла для выполнения вызова API и возвращаем пост, который хранится в переменной post через setPost в методе then, который имеет доступ к ответу API.
Ответ возвращает объект со свойством data, которое в данном случае является объектом с id, title, body и userId, затем мы используем title и body поста для монтажа поста на экран.
Выполнение POST-запросов
Для создания ресурса на сервере мы используем метод POST, давайте создадим пример создания нового поста.
Конечной точкой для создания нового поста является /post с указанием заголовка и тела в запросе.
...
function handleCreatePost() {
axios
.post(baseUrl, {
title: "Titulo do Post",
body: "Esse é um novo post e foi criado em um exemplo de uso do axios, não é incrível?",
})
.then(({ data }) => setPosts(data));
}
return (
<div className="container">
<h1>Postagens</h1>
<hr />
{posts ? (
<>
<h2 className="post-title">{posts.title}</h2>
<p className="post-body">{posts.body}</p>
<div className="container-crud-btns">
<button onClick={handleCreatePost} className="post-btn">
Create post
</button>
<button onClick={handleUpdatePost} className="post-btn">
Update post
</button>
</div>
</>
) : (
<h2 className="post-title">Nenhum Post Disponível</h2>
)}
</div>
);
В axios, как уже говорилось, есть функции с именем http-методов, в данном случае мы используем функцию post()
, чтобы выполнить создание нового поста, мы добавляем кнопку и в событии onClick вызываем функцию handleCreatePost, которая выполняет запрос на создание поста.
В функции axios post()
мы передаем конечную точку /posts, а в качестве второго аргумента передается объект, содержащий заголовок и тело поста. Возвратом API ( .then()
) является созданный пост, который мы храним в состоянии posts.
Просто для эстетической цели я добавил h1 и hr для лучшего представления на экране.
Выполнение запросов PUT
Для выполнения обновления ресурса на сервере мы используем метод PUT, давайте создадим пример создания нового поста.
...
function handleUpdatePost() {
axios
.post(baseUrl, {
title: "Novo Titulo do Post",
body: "Esse é um novo post e foi atualizado em um exemplo de uso do axios, não é incrível?",
})
.then(({ data }) => setPosts(data));
}
return (
<div className="container">
<h1>Postagens</h1>
<hr />
{posts ? (
<>
<h2 className="post-title">{posts.title}</h2>
<p className="post-body">{posts.body}</p>
<div className="container-crud-btns">
<button onClick={handleCreatePost} className="post-btn">
Create post
</button>
<button onClick={handleUpdatePost} className="post-btn">
Update post
</button>
</div>
</>
) : (
<h2 className="post-title">Nenhum Post Disponível</h2>
)}
</div>
);
Как и в примере с методом Post, мы добавляем новую кнопку и создаем функцию handleUpdatePost, которая выполняет обновление, функция put()
так же, как и post()
получает конечную точку (в данном случае это id обновляемого поста) и возвращает обновленный пост, который мы снова добавляем в состояние posts.
Выполнение запросов DELETE
Для выполнения удаления ресурсов на сервере мы используем метод DELETE, давайте создадим пример удаления поста.
...
function handleDeletePost() {
axios.delete(`${baseUrl}/1`).then(() => {
alert("Post deleted!");
setPosts(null);
});
}
return (
<div className="container">
<h1>Postagens</h1>
<hr />
{posts ? (
<>
<h2 className="post-title">{posts.title}</h2>
<p className="post-body">{posts.body}</p>
<div className="container-crud-btns">
<button onClick={handleCreatePost} className="post-btn">
Create post
</button>
<button onClick={handleUpdatePost} className="post-btn">
Update post
</button>
<button onClick={handleDeletePost} className="post-btn">
Delete post
</button>
</div>
</>
) : (
<h2 className="post-title">Nenhum Post Disponível</h2>
)}
</div>
);
}
В случае с удалением мы также создаем новую кнопку и функцию handleDeletePost, которая выполняет удаление поста с указанным id, в возврате нет данных, но важно гарантировать, что запрос был выполнен успешно.
Для обновления интерфейса мы установим состояние posts равным null, что при обработке кода вернет сообщение ‘No Post Available’.
Работа с ошибками в Axios
Если в запросе возникает ошибка, либо при отправке неверных данных, либо при сбое сети, либо при неправильной конечной точке, это обрабатывается в функции catch(), которая имеет доступ к возвращаемой ошибке, и ей может быть присвоено состояние для обработки в пользовательском интерфейсе.
...
axios
.put(`${baseUrl}/1`, {
title: "Novo Titulo do Post",
body: "Esse é um novo post e foi atualizado em um exemplo de uso do axios, não é incrível?",
})
.then(({ data }) => setPosts(data))
.catch((error) => setError("error" + error));
Создание экземпляра Axios
В axios мы можем создать экземпляр с базовым URL API с помощью функции create()
, плюс другие значения, которые вы можете указать в каждом запросе в качестве заголовков.
const client = axios.create({
baseURL: "https://jsonplaceholder.typicode.com/posts"
});
// uso
client.get("/post").then()
При вызове клиента возвращается экземпляр с заданным baseURL, при этом в параметре мы передаем только нужный маршрут, например /
| /post
и т.д.
Использование async – await с Axios
Async-await позволяет писать гораздо более чистый код без функций then и catch для возвратов. Кроме того, код с async-await очень похож на синхронный код, и его легче понять.
Пример функции useEffect с использованием async-await
...
useEffect(() => {
async function getPosts() {
try {
const response = await axios.get(`${baseUrl}/1`);
setPosts(response.data);
} catch (error) {
setError(error);
}
}
getPosts();
}, []);
Чтобы иметь возможность использовать async await, необходимо создать функцию с именем getPosts() в данном случае и вызвать ее в последовательности, это может быть IIFE, мы используем try catch внутри функции для отлова возможных ошибок.
#### Flow async await:
- Объявление функции со словом async (позволяет использовать await внутри функции).
- await ожидает возврата обещания (axios всегда возвращает обещание из запросов).
- Только после возврата await будет выполнена следующая строка.
- В данном случае try и catch используются для обработки ошибок в запросе.
Async Await делает код чистым и может быть легко использован с axios.
Создание пользовательского крючка useAxios
Пользовательские хуки используются для удаления логики, которая может быть повторно использована в различных компонентах, здесь намерение просто показать, что мы можем оставить компонент Post чище и оставить всю логику запроса в хуке useAxios, в нем мы также имеем дело с другим состоянием, загрузкой, которая служит для работы с элементом загрузки на экране.
Пример кода для useAxios
import { useEffect, useState } from "react";
import axios from "axios";
const api = axios.create({
baseURL: "https://jsonplaceholder.typicode.com/posts",
});
export const useAxios = () => {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function getPosts() {
try {
setLoading(true);
setError(null);
const response = await api.get(`/1`);
setData(response.data);
} catch (error) {
setError(error);
setData(null);
} finally {
setLoading(false);
}
}
getPosts();
}, []);
function handleCreatePost() {
setLoading(true);
setError(null);
api.post("/", {
title: "Titulo do Post",
body: "Esse é um novo post e foi criado em um exemplo de uso do axios, não é incrível?",
})
.then(({ data }) => {
setData(data);
})
.catch((error) => setError("error" + error));
setLoading(false);
}
function handleUpdatePost() {
setLoading(true);
setError(null);
api.put(`/1`, {
title: "Novo Titulo do Post",
body: "Esse é um novo post e foi atualizado em um exemplo de uso do axios, não é incrível?",
})
.then(({ data }) => {
setData(data);
})
.catch((error) => setError("error" + error));
setLoading(false);
}
function handleDeletePost() {
setLoading(true);
setError(null);
api.delete(`/1`)
.then(() => {
alert("Post deleted!");
setData(null);
})
.catch((error) => setError("error" + error));
setLoading(false);
}
function handleError() {
setLoading(true);
setError(null);
api.get(`/asdf`)
.then(({ data }) => setData(data))
.catch((err) => {
setData(null);
setError("error" + err);
});
setLoading(false);
}
return {
data,
error,
loading,
handleCreatePost,
handleUpdatePost,
handleDeletePost,
handleError,
};
};
Этот хук более специфичен для нашего примера с постом, но может быть и более общим, получая url в качестве параметра, с более надежной логикой, но для примера подойдет и этот.
Таким образом, помимо данных, возвращаемых состояниями, мы можем также возвращать функции, которые занимаются CRUD, что делает наш компонент Post намного чище и улучшает обслуживание.
Полный код нашего примера
// Componente Post - Sem utilizar o useAxios
import React, { useEffect, useState } from "react";
import axios from "axios";
import "./Post.css";
const baseUrl = "https://jsonplaceholder.typicode.com/posts";
export function Post() {
const [posts, setPosts] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
async function getPosts() {
try {
const response = await axios.get(`${baseUrl}/1`);
setPosts(response.data);
} catch (error) {
setError(error);
}
}
getPosts();
}, []);
function handleCreatePost() {
axios
.post(baseUrl, {
title: "Titulo do Post",
body: "Esse é um novo post e foi criado em um exemplo de uso do axios, não é incrível?",
})
.then(({ data }) => setPosts(data))
.catch((error) => setError("error" + error));
}
function handleUpdatePost() {
axios
.put(`${baseUrl}/1`, {
title: "Novo Titulo do Post",
body: "Esse é um novo post e foi atualizado em um exemplo de uso do axios, não é incrível?",
})
.then(({ data }) => setPosts(data))
.catch((error) => setError("error" + error));
}
function handleDeletePost() {
axios
.delete(`${baseUrl}/1`)
.then(() => {
alert("Post deleted!");
setPosts(null);
})
.catch((error) => setError("error" + error));
}
function handleError() {
axios
.get(`${baseUrl}/asdf`)
.then(({ data }) => setPosts(data))
.catch((err) => {
setPosts(null);
setError("error" + err);
});
}
return (
<div className="container">
<h1>Postagens</h1>
<hr />
{posts ? (
<>
<h2 className="post-title">{posts.title}</h2>
<p className="post-body">{posts.body}</p>
<div className="container-crud-btns">
<button onClick={handleCreatePost} className="post-btn">
Create post
</button>
<button onClick={handleUpdatePost} className="post-btn">
Update post
</button>
<button onClick={handleDeletePost} className="post-btn">
Delete post
</button>
<button onClick={handleError} className="post-btn">
Error post
</button>
</div>
</>
) : (
<h2 className="post-title">Nenhum Post Disponível</h2>
)}
{error && <p>Ocorreu na requisição: {error}</p>}
</div>
);
}
С помощью крючка UseAxios.
// Componente Post - Utilizando o useAxios
import React from "react";
import "./Post.css";
import { useAxios } from "./useAxios";
export function PostUseAxios() {
const {
data,
error,
loading,
handleCreatePost,
handleUpdatePost,
handleDeletePost,
handleError,
} = useAxios();
if (loading)
return (
<div className="container">
<h1>Postagens</h1>
<p>Carregando...</p>
</div>
);
return (
<div className="container">
<h1>Postagens</h1>
<hr />
{data ? (
<>
<h2 className="post-title">{data.title}</h2>
<p className="post-body">{data.body}</p>
<div className="container-crud-btns">
<button onClick={handleCreatePost} className="post-btn">
Create post
</button>
<button onClick={handleUpdatePost} className="post-btn">
Update post
</button>
<button onClick={handleDeletePost} className="post-btn">
Delete post
</button>
<button onClick={handleError} className="post-btn">
Error post
</button>
</div>
</>
) : (
<h2 className="post-title">Nenhum Post Disponível</h2>
)}
{error && <p>Ocorreu na requisição: {error}</p>}
</div>
);
}
В основном, чтобы использовать функцию useAxios, мы просто импортируем ее в файл и используем, вызывая функцию useAxios
, которая возвращает объект, содержащий данные и функции о посте.
И вот результат на экране
CSS был опущен, так как он не является основной темой статьи, вы можете получить доступ к репозиторию по ссылке в конце статьи.
Уффа !!! статья была немного длинной, но это самое необходимое об обработке/запросах, что нам нужно иметь для работы с axios.
По материалам поста : How To Use Axios With React: The Definitive Guide (2021)
Пример кода: Репозиторий – экосистема React
Этот пост призван помочь тем, кто начинает изучать React, и послужить стимулом в моем изучении React при создании других постов для закрепления полученных знаний.
Следуйте за мной 🙂
Github | Linkedin