Original article: How To Use Axios With React: The Definitive Guide (2021)

En esta guía, aprenderás cómo usar Axios.js con React usando toneladas de ejemplos del mundo real con hooks de React.

Veras por qué debería usar Axios como una biblioteca de obtención de datos, cómo configurarlo con React y realizar todo tipo de solicitud HTTP con él.

Luego, hablaremos de funciones más avanzadas, como la creación de una instancia de Axios para la reutilización, el uso de async-await con Axios para simplificar y cómo usar Axios como un hook personalizado.

Empecemos!

Tabla de contenido

¿Qué es Axios?

Axios es una biblioteca de cliente HTTP que le permite realizar solicitudes a un endpoint determinado:

Screen-Shot-2021-07-12-at-1.14.41-PM

Esto podría ser una API externa o su propio servidor backend Node.js, por ejemplo.

Al realizar una solicitud, se espera que su API realice una operación de acuerdo con la solicitud que realizaste.

Por ejemplo, si realizas una solicitud GET, esperas obtener datos para mostrar en su aplicación.

Por qué usar Axios en React

Hay varias bibliotecas diferentes que puede usar para realizar estas solicitudes, entonces, ¿por qué elegir Axios?

Aquí hay cinco razones por las que debería usar Axios como su cliente para realizar solicitudes HTTP:

  1. Tiene buenos valores predeterminados para trabajar con datos JSON. A diferencia de alternativas como Fetch API, a menudo no necesita configurar sus encabezados. O realice tareas tediosas como convertir el cuerpo de su solicitud en una cadena JSON.
  2. Axios tiene nombres de funciones que coinciden con cualquier método HTTP. Para realizar una solicitud GET, utiliza el método .get().
  3. Axios hace más con menos código. A diferencia de Fetch API, solo necesita una devolución de llamada .then() para acceder a los datos JSON solicitados.
  4. Axios tiene un mejor manejo de errores. Axios arroja 400 y 500 errores de rango por nosotros. A diferencia de Fetch API, donde debe verificar el código de estado y arrojar el error nosotros mismo.
  5. Axios se puede utilizar tanto en el servidor como en el cliente. Si está escribiendo una aplicación en Node.js, tenga en cuenta que Axios también se puede usar en un entorno separado del navegador.

Cómo configurar Axios con React

Usar Axios con React es un proceso muy simple. Necesitas tres cosas:

  1. Un proyecto React existente
  2. Para instalar Axios con npm/yarn
  3. Un endpoint API para realizar solicitudes

La forma más rápida de crear una nueva aplicación React es yendo a react.new.

Si tienes un proyecto React existente, solo necesita instalar Axios con npm (o cualquier otro administrador de paquetes):

npm install axios

En esta guía, utilizarás la API de JSON Placeholder para obtener y cambiar los datos de las publicaciones.

Aquí hay una lista de todas las diferentes rutas a las que puede realizar solicitudes, junto con el método HTTP apropiado para cada una:

Screen-Shot-2021-07-10-at-12.21.28-PM

Aquí hay un ejemplo rápido de todas las operaciones que realizarás con Axios y endpoint API: — recuperar, crear, actualizar y eliminar publicaciones:

axios-react

Cómo hacer una solicitud GET

Para obtener datos o recuperarlos, realiza una solicitud GET.

Primero, vas a hacer una solicitud de publicaciones individuales. Si observa el endpoint, obtendrás la primera publicación del endpoint /posts:

import axios from "axios";
import React from "react";

const baseURL = "https://jsonplaceholder.typicode.com/posts/1";

export default function App() {
  const [post, setPost] = React.useState(null);

  React.useEffect(() => {
    axios.get(baseURL).then((response) => {
      setPost(response.data);
    });
  }, []);

  if (!post) return null;

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
    </div>
  );
}

Para realizar esta solicitud, cuando se monta el componente, utiliza el hook useEffect. Esto implica importar Axios, usar el método .get() para realizar una solicitud GET a su endpoint y usar el callback .then() para recuperar todos los datos de respuesta.

Note that you can always find the requested data from the .data property in the response. Ten en cuenta que siempre puede encontrar los datos solicitados de la propiedad .data en la respuesta.

Cómo hacer una solicitud POST

Para crear nuevos datos, realiza una solicitud POST.

De acuerdo con la API, esto debe realizarse hacia el endpoint /posts. Si observas el código a continuación, verás que hay un botón para crear una publicación:

import axios from "axios";
import React from "react";

const baseURL = "https://jsonplaceholder.typicode.com/posts";

export default function App() {
  const [post, setPost] = React.useState(null);

  React.useEffect(() => {
    axios.get(`${baseURL}/1`).then((response) => {
      setPost(response.data);
    });
  }, []);

  function createPost() {
    axios
      .post(baseURL, {
        title: "Hello World!",
        body: "This is a new post."
      })
      .then((response) => {
        setPost(response.data);
      });
  }

  if (!post) return "No post!"

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
      <button onClick={createPost}>Create Post</button>
    </div>
  );
}

Cuando haces clic en el botón, llama a la función createPost.

Para realizar esa solicitud POST con Axios, utiliza el método .post(). Como segundo argumento, incluye una propiedad de objeto que especifica cómo deseas que sea la nueva publicación.

Una vez más, usa el callback .then() para recuperar los datos de respuesta y reemplaza la primera publicación que recibiste con la nueva publicación que solicitaste.

Esto es muy similar al método .get(), pero el nuevo recurso que deseas crear se proporciona como el segundo argumento después del endpoint del API.

Cómo hacer una solicitud PUT

Para actualizar un recurso determinado, realiza una solicitud PUT.

En este caso, actualizarás la primera publicación.

Para ello, volverás a crear un botón. Pero esta vez, el botón llamará a una función para actualizar una publicación:

import axios from "axios";
import React from "react";

const baseURL = "https://jsonplaceholder.typicode.com/posts";

export default function App() {
  const [post, setPost] = React.useState(null);

  React.useEffect(() => {
    axios.get(`${baseURL}/1`).then((response) => {
      setPost(response.data);
    });
  }, []);

  function updatePost() {
    axios
      .put(`${baseURL}/1`, {
        title: "Hello World!",
        body: "This is an updated post."
      })
      .then((response) => {
        setPost(response.data);
      });
  }

  if (!post) return "No post!"

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
      <button onClick={updatePost}>Update Post</button>
    </div>
  );
}

En el código anterior, utilizaste el método PUT de Axios. Y al igual que con el método POST, incluye las propiedades que deseas que estén en el recurso actualizado.

Nuevamente, usando la devolución de llamada .then(), actualiza el JSX con los datos que se devuelven.

Cómo hacer una solicitud de ELIMINACIÓN

Finalmente, para eliminar un recurso, utiliza el método DELETE.

Como ejemplo, eliminaremos la primera publicación.

Ten en cuenta que no necesitas ningún segundo argumento para realizar esta solicitud:

import axios from "axios";
import React from "react";

const baseURL = "https://jsonplaceholder.typicode.com/posts";

export default function App() {
  const [post, setPost] = React.useState(null);

  React.useEffect(() => {
    axios.get(`${baseURL}/1`).then((response) => {
      setPost(response.data);
    });
  }, []);

  function deletePost() {
    axios
      .delete(`${baseURL}/1`)
      .then(() => {
        alert("Post deleted!");
        setPost(null)
      });
  }

  if (!post) return "No post!"

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
      <button onClick={deletePost}>Delete Post</button>
    </div>
  );
}

En la mayoría de los casos, no necesita los datos que se devuelven desde el método .delete().

Pero en el código anterior, el callback .then() todavía se usa para garantizar que su solicitud se resuelva con éxito.

En el código anterior, después de eliminar una publicación, se alerta al usuario de que se eliminó correctamente. Luego, los datos de la publicación se borran del estado al configurarlos en su valor inicial de null.

Además, una vez que se elimina una publicación, el texto "No post" se muestra inmediatamente después del mensaje de alerta.

Cómo manejar errores con Axios

¿Qué pasa con el manejo de errores con Axios?

¿Qué pasa si hay un error al hacer una solicitud? Por ejemplo, es posible que transmita datos incorrectos, realizar una solicitud al endpoint incorrecto o tener un error de red.

Para simular un error, enviarás una solicitud a un extremo de la API que no existe: /posts/asdf.

Esta solicitud devolverá un código de estado 404:

import axios from "axios";
import React from "react";

const baseURL = "https://jsonplaceholder.typicode.com/posts";

export default function App() {
  const [post, setPost] = React.useState(null);
  const [error, setError] = React.useState(null);

  React.useEffect(() => {
    // invalid url will trigger an 404 error
    axios.get(`${baseURL}/asdf`).then((response) => {
      setPost(response.data);
    }).catch(error => {
      setError(error);
    });
  }, []);
  
  if (error) return `Error: ${error.message}`;
  if (!post) return "No post!"

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
    </div>
  );
}

En este caso, en lugar de ejecutar el callback .then(), Axios generará un error y ejecutará el callback .catch().

En esta función, estamos tomando los datos del error y poniéndolos en estado para alertar a nuestro usuario sobre el error. Entonces, si tenemos un error, mostraremos ese mensaje de error.

Cuando ejecutes este código de código, verás el texto "Error: Request failed with status code 404".

Cómo crear una instancia de Axios

Si observas los ejemplos anteriores, verá que hay una baseURL que usamos como parte del endpoint para que Axios realice estas solicitudes.

Sin embargo, se vuelve un poco tedioso seguir escribiendo esa baseURL para cada solicitud. ¿No podría simplemente hacer que Axios recuerde qué baseURL está usando, ya que siempre involucra un punto final similar?

De hecho, puedes. Si creas una instancia con el método .create(), Axios recordará esa baseURL, además de otros valores que quizás desees especificar para cada solicitud, incluidos los encabezados:

import axios from "axios";
import React from "react";

const client = axios.create({
  baseURL: "https://jsonplaceholder.typicode.com/posts" 
});

export default function App() {
  const [post, setPost] = React.useState(null);

  React.useEffect(() => {
    client.get("/1").then((response) => {
      setPost(response.data);
    });
  }, []);

  function deletePost() {
    client
      .delete("/1")
      .then(() => {
        alert("Post deleted!");
        setPost(null)
      });
  }

  if (!post) return "No post!"

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
      <button onClick={deletePost}>Delete Post</button>
    </div>
  );
}

La única propiedad en el objeto de configuración anterior es baseURL, a la que pasa el endpoint.

La función .create() devuelve una instancia recién creada, que en este caso se llama client.

Luego, en el futuro, puedes usar todos los mismos métodos que usaste antes, pero ya no tienes que incluir la baseURL como el primer argumento. Solo tiene que hacer referencia a la ruta específica que desea, por ejemplo, /, /1, etc.

Cómo usar la sintaxis Async-Await con Axios

Un gran beneficio de usar promesas en JavaScript (incluidas las aplicaciones React) es la sintaxis async-await.

Async-await te permite escribir un código mucho más limpio sin los callbacks then y catch. Además, el código con async-await se parece mucho al código síncrono y es más fácil de entender.

Pero, ¿cómo se usa la sintaxis async-await con Axios?

En el siguiente ejemplo, se recuperan las publicaciones y todavía hay un botón para eliminar esa publicación:

import axios from "axios";
import React from "react";

const client = axios.create({
  baseURL: "https://jsonplaceholder.typicode.com/posts" 
});

export default function App() {
  const [post, setPost] = React.useState(null);

  React.useEffect(() => {
    async function getPost() {
      const response = await client.get("/1");
      setPost(response.data);
    }
    getPost();
  }, []);

  async function deletePost() {
    await client.delete("/1");
    alert("Post deleted!");
    setPost(null);
  }

  if (!post) return "No post!"

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
      <button onClick={deletePost}>Delete Post</button>
    </div>
  );
}

Sin embargo, en useEffect, hay una función async llamada getPost.

Hacerlo async te permite usar la palabra clave await para resolver la solicitud GET y establecer esos datos en estado en la siguiente línea sin la devolución de llamada .then().

Ten en cuenta que la función getPost se llama inmediatamente después de su creación.

Además, la función deletePost ahora es async, lo cual es un requisito para usar la palabra clave   que resuelve la promesa que devuelve (todos los métodos de Axios devuelven una promesa para resolver).

Después de usar la palabra clave await con la solicitud DELETE, se alerta al usuario de que la publicación se eliminó y la publicación se establece en null.

Como puedes ver, async-await limpia mucho el código y puedes usarlo con Axios muy fácilmente.

Cómo crear un hook useAxios personalizado

Async-await es una excelente manera de simplificar su código, pero puede llevar esto un paso más allá.

En lugar de usar useEffect para obtener datos cuando se monta el componente, puedes crear su propio hook personalizado con Axios para realizar la misma operación que una función reutilizable.

Si bien puedes crear este hook personalizado por ti mismo, hay una biblioteca muy buena que te brinda un hook personalizado useAxios llamado use-axios-client.

Primero, instala el paquete:

npm install use-axios-client

Para usar el hook en sí, importa useAxios desde use-axios-client en la parte superior del componente.

Como ya no necesitas useEffect, puede eliminar la importación de React:

import { useAxios } from "use-axios-client";

export default function App() {
  const { data, error, loading } = useAxios({
    url: "https://jsonplaceholder.typicode.com/posts/1"
  });

  if (loading || !data) return "Loading...";
  if (error) return "Error!";

  return (
    <div>
      <h1>{data.title}</h1>
      <p>{data.body}</p>
    </div>
  ) 
}

Ahora puedes llamar a useAxios en la parte superior del componente de la aplicación, pasar la URL a la que desea realizar una solicitud y el hook devuelve un objeto con todos los valores que necesita para manejar los diferentes estados: loading, error y data resueltos .

En el proceso de realizar esta solicitud, el valor de loading será verdadero. Si hay un error, querrás mostrar ese estado de error. De lo contrario, si tiene los datos devueltos, puede mostrarlos en la interfaz de usuario.

El beneficio de los hooks personalizados como este es que realmente reduce el código y lo simplifica en general.

Si estás buscando una manera de obtener datos aún más simple con Axios, prueba un gancho de useAxios personalizado como este.

¿Qué sigue?

¡Felicidades! Ahora sabes cómo usar una de las bibliotecas de clientes HTTP más poderosas para potenciar sus aplicaciones React.

Espero que hayas sacado mucho provecho de esta guía.