React – Работа с данными с помощью Axios

Изучение того, как выполнять вызовы 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

Оцените статью
Procodings.ru
Добавить комментарий