Руководство для начинающих по использованию REST API в React


Введение

React — это популярный фронтенд-фреймворк, который разработчики используют для создания приложений. В какой-то момент вам понадобится интегрировать API в ваше приложение React, если вы хотите создавать реальные приложения. Каждый разработчик, который хочет создавать современные, реально работающие веб-приложения на React, должен понимать, как использовать API для получения данных в приложениях React.

В этом руководстве для начинающих мы узнаем, как использовать RESTful API в React, включая получение, удаление и добавление данных. Мы также рассмотрим два основных способа потребления RESTful API и то, как использовать их с помощью хуков React.

Что такое REST API?

Если вы когда-нибудь занимались программированием или изучали программирование, вы почти наверняка сталкивались с термином «API». API означает интерфейс прикладного программирования, и это средство, которое позволяет различным приложениям программно взаимодействовать друг с другом и получать ответ в режиме реального времени.

В 2000 году Рой Филдинг определил REST как архитектурный стиль и методологию, широко используемые при разработке интернет-сервисов, таких как распределенные гипермедийные системы. Это аббревиатура, которая расшифровывается как «REpresentational State Transfer».

Когда запрос выполняется через REST API, он отправляет представление текущего состояния ресурса запросчику или конечной точке. Это представление состояния может принимать форму JSON (JavaScript Object Notation), XML или HTML. JSON является наиболее широко используемым форматом файлов, поскольку он не зависит от языка и может быть прочитан как человеком, так и машиной.

Например:

[
   {
      "userId": 1,
      "id": 1,
      "title": "sunt excepturi",
      "body": "quia et suscipitnsuscipit recusandae consequuntur "
   },
   {
      "userId": 1,
      "id": 2,
      "title": "qui est esse",
      "body": "est rerum tempore vitaensequi sint nihil"
   }
]
Войти в полноэкранный режим Выход из полноэкранного режима

Потребление REST API в React

Потребление REST API в React-приложении может быть реализовано различными способами, но в этом руководстве мы рассмотрим два наиболее популярных подхода: Axios (HTTP-клиент на основе обещаний) и Fetch API (встроенный в браузер веб-API).

Примечание: Чтобы полностью понять это руководство, вы должны быть знакомы с JavaScript, React и React hooks, поскольку они занимают в нем центральное место.

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

  • хук useEffect: В React мы выполняем API-запросы внутри хука useEffect() так, чтобы рендеринг происходил либо сразу при запуске приложения, либо после достижения определенного состояния. Вот общий синтаксис, который будет использоваться:
useEffect(() => {
    // data fetching here
}, []);
Войти в полноэкранный режим Выйти из полноэкранного режима
  • Крючок useState: Когда мы запрашиваем данные, мы должны подготовить состояние, в котором они будут храниться после возврата. Мы можем сохранить его в инструменте управления состоянием, таком как Redux, или в объекте контекста. Чтобы не усложнять ситуацию, мы будем хранить возвращаемые данные в локальном состоянии React.
const [posts, setPosts] = useState([]);
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь перейдем к основной части этого руководства, где мы узнаем, как получать, добавлять и удалять данные с помощью API постов JSONPlaceholder. Эти знания применимы к любому типу API, поскольку данное руководство предназначено для новичков.

Потребление API с помощью Fetch API

Fetch API — это встроенный метод JavaScript для получения ресурсов с сервера или конечной точки API. Он является встроенным и не требует установки каких-либо зависимостей или пакетов.

Метод fetch() требует обязательного аргумента, которым является путь или URL к ресурсу, который вы хотите получить, а затем возвращает Promise, чтобы вы могли обработать успех или неудачу с помощью методов then() и catch().

Базовый запрос на выборку очень прост в написании и выглядит следующим образом: Мы просто получаем данные из URL, который возвращает данные в формате JSON, а затем записываем их в консоль:

fetch('https://jsonplaceholder.typicode.com/posts?_limit=10')
   .then(response => response.json())
   .then(data => console.log(data));
Вход в полноэкранный режим Выход из полноэкранного режима

Примечание: Ответ по умолчанию обычно представляет собой обычный HTTP-ответ, а не реальный JSON, но мы можем получить наш вывод в виде JSON-объекта, используя метод json() ответа.

Выполнение GET-запроса в React с помощью Fetch API

Метод HTTP GET может быть использован для запроса данных из конечной точки; как уже говорилось ранее, Fetch API принимает один обязательный аргумент, который является истинным; он также принимает аргумент option, который является необязательным, особенно при использовании метода GET, который используется по умолчанию; однако для других методов, таких как POST и DELETE, необходимо присоединить метод к массиву options:

fetch(url, {
    method: "GET" // default, so we can ignore
})
Войти в полноэкранный режим Выйти из полноэкранного режима

Итак, мы узнали, как все работает, поэтому давайте соберем все, что мы узнали, вместе и выполним запрос get, чтобы получить данные из нашего API. Как уже говорилось ранее, мы будем использовать бесплатный онлайн API JSONPlaceholder для получения списка постов в нашем приложении:

import React, { useState, useEffect } from 'react';

const App = () => {
   const [posts, setPosts] = useState([]);
   useEffect(() => {
      fetch('https://jsonplaceholder.typicode.com/posts?_limit=10')
         .then((response) => response.json())
         .then((data) => {
            console.log(data);
            setPosts(data);
         })
         .catch((err) => {
            console.log(err.message);
         });
   }, []);

return (
   // ... consume here
);
};
Вход в полноэкранный режим Выход из полноэкранного режима

В предыдущем коде мы создали состояние для хранения данных, которые мы получим из API, чтобы мы могли использовать их позже в нашем приложении, и мы также установили значение по умолчанию — пустой массив.

const [posts, setPosts] = useState([]);
Вход в полноэкранный режим Выход из полноэкранного режима

Основная операция происходит в состоянии useEffect, так что данные/посты будут получены, как только приложение загрузится. Запрос на выборку дает обещание, которое мы можем либо принять, либо отклонить:

useEffect(() => {
   fetch('https://jsonplaceholder.typicode.com/posts?_limit=10').then(
      (response) => console.log(response)
   );
}, []);
Войти в полноэкранный режим Выйти из полноэкранного режима

Этот ответ содержит большое количество данных, таких как код состояния, текст и другую информацию, которая понадобится для обработки ошибок в дальнейшем. До сих пор мы выполняли resolve с помощью .then(), но он возвращал объект ответа, а это не то, что мы хотели, поэтому нам нужно преобразовать объект Response в формат JSON с помощью метода json(), который также возвращает обещание для получения фактических данных с помощью второго .then().

useEffect(() => {
   fetch('https://jsonplaceholder.typicode.com/posts?_limit=10')
      .then((response) => response.json())
      .then((data) => {
         console.log(data);
         setPosts(data);
      });
}, []);
Вход в полноэкранный режим Выход из полноэкранного режима

Если мы посмотрим на консоль, то увидим, что мы получили 10 постов из нашего API, которые мы также установили в состояние, указанное ранее. Работа не завершена, поскольку мы обработали только разрешение обещания, но не отказ обещания, который обрабатывается с помощью метода .catch():

useEffect(() => {
   fetch('https://jsonplaceholder.typicode.com/posts?_limit=10')
      .then((response) => response.json())
      .then((data) => {
         console.log(data);
         setPosts(data);
      })
      .catch((err) => {
         console.log(err.message);
      });
}, []);
Вход в полноэкранный режим Выход из полноэкранного режима

До сих пор мы видели, как выполнить запрос GET, который может быть легко использован в нашей программе с помощью цикла по нашему массиву:

const App = () => {
// ...

   return (
   <div className="posts-container">
      {posts.map((post) => {
         return (
            <div className="post-card" key={post.id}>
               <h2 className="post-title">{post.title}</h2>
               <p className="post-body">{post.body}</p>
               <div className="button">
               <div className="delete-btn">Delete</div>
               </div>
            </div>
         );
      })}
   </div>
   );
};

export default App;
Вход в полноэкранный режим Выход из полноэкранного режима

Выполнение POST-запроса в React с помощью Fetch API

Метод HTTP POST можно использовать для отправки данных с конечной точки; он работает аналогично запросу GET, с той лишь разницей, что метод и два дополнительных параметра должны быть добавлены к дополнительному объекту:

const addPosts = async (title, body) => {
await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
body: JSON.stringify({
   title: title,
   body: body,
   userId: Math.random().toString(36).slice(2),
}),
headers: {
   'Content-type': 'application/json; charset=UTF-8',
},
})
.then((response) => response.json())
.then((data) => {
   setPosts((posts) => [data, ...posts]);
   setTitle('');
   setBody('');
})
.catch((err) => {
   console.log(err.message);
});
};
Войти в полноэкранный режим Выйти из полноэкранного режима

Основными параметрами, которые покажутся странными, являются тело и заголовок. Тело содержит данные, которые мы хотим передать в API, которые мы должны сначала строчить, поскольку мы отправляем данные на веб-сервер, а заголовок указывает тип данных, который всегда одинаков при использовании REST API. Мы также устанавливаем состояние для хранения новых данных и распределяем оставшиеся данные в массив.

Если посмотреть на созданный нами метод addPost(), то он ожидает эти данные от формы или чего-то еще; в нашем случае я создал форму, получил данные формы через состояния, а затем добавил их в метод, когда форма была отправлена:

import React, { useState, useEffect } from 'react';
const App = () => {
const [title, setTitle] = useState('');
const [body, setBody] = useState('');
// ...
const addPosts = async (title, body) => {
   await fetch('https://jsonplaceholder.typicode.com/posts', {
      method: 'POST',
      body: JSON.stringify({
         title: title,
         body: body,
         userId: Math.random().toString(36).slice(2),
      }),
      headers: {
         'Content-type': 'application/json; charset=UTF-8',
      },
   })
      .then((response) => response.json())
      .then((data) => {
         setPosts((posts) => [data, ...posts]);
         setTitle('');
         setBody('');
      })
      .catch((err) => {
         console.log(err.message);
      });
};

const handleSubmit = (e) => {
   e.preventDefault();
   addPosts(title, body);
};    

return (
   <div className="app">
      <div className="add-post-container">
         <form onSubmit={handleSubmit}>
            <input type="text" className="form-control" value={title}
               onChange={(e) => setTitle(e.target.value)}
            />
            <textarea name="" className="form-control" id="" cols="10" rows="8" 
               value={body} onChange={(e) => setBody(e.target.value)} 
            ></textarea>
            <button type="submit">Add Post</button>
         </form>
      </div>
      {/* ... */}
   </div>
);
};

export default App;
Войти в полноэкранный режим Выход из полноэкранного режима

Выполнение запроса DELETE в React с помощью Fetch API

Метод HTTP DELETE можно использовать для удаления данных из конечной точки; он работает аналогично запросу GET, с основным отличием в добавлении метода:

const deletePost = async (id) => {
await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`, {
   method: 'DELETE',
}).then((response) => {
   if (response.status === 200) {
      setPosts(
         posts.filter((post) => {
            return post.id !== id;
         })
      );
   } else {
      return;
   }
});
};
Войти в полноэкранный режим Выйти из полноэкранного режима

Этот метод срабатывает при нажатии на кнопку, и мы получаем id конкретного поста, в котором была нажата кнопка, а затем мы удаляем эти данные из всех восстановленных данных. Эти данные будут удалены из API, но не сразу из пользовательского интерфейса, поэтому мы добавили фильтр для удаления этих данных. Для каждого элемента в цикле кнопка удаления будет выглядеть следующим образом:

const App = () => {
// ...

   return (
   <div className="posts-container">
      {posts.map((post) => {
         return (
            <div className="post-card" key={post.id}>
               {/* ... */}
               <div className="button">
                  <div className="delete-btn" onClick={() => deletePost(post.id)}>
                     Delete
                  </div>
               </div>    
            </div>
         );
      })}
   </div>
   );
};

export default App;
Вход в полноэкранный режим Выход из полноэкранного режима

Использование Async/Await в Fetch API

До сих пор мы видели, как выполнять запросы на выборку, используя синтаксис обещания, который иногда может быть запутанным. Далее идет цепочка. Мы можем избежать цепочки с помощью Async/await и написать более читабельный код.

Чтобы использовать async/await, сначала вызовите async в функции, а затем при выполнении запроса и ожидании ответа добавьте синтаксис await перед функцией, чтобы подождать, пока обещание не придет с результатом.

Когда мы используем async/await, все наши запросы Fetch будут выглядеть следующим образом:

import React, { useState, useEffect } from 'react';

const App = () => {
   const [title, setTitle] = useState('');
   const [body, setBody] = useState('');
   const [posts, setPosts] = useState([]);

   // GET with fetch API
   useEffect(() => {
      const fetchPost = async () => {
         const response = await fetch(
            'https://jsonplaceholder.typicode.com/posts?_limit=10'
         );
         const data = await response.json();
         console.log(data);
         setPosts(data);
      };
      fetchPost();
   }, []);

   // Delete with fetchAPI
   const deletePost = async (id) => {
      let response = await fetch(
         `https://jsonplaceholder.typicode.com/posts/${id}`,
         {
            method: 'DELETE',
         }
      );
      if (response.status === 200) {
         setPosts(
            posts.filter((post) => {
               return post.id !== id;
            })
         );
      } else {
         return;
      }
   };

   // Post with fetchAPI
   const addPosts = async (title, body) => {
      let response = await fetch('https://jsonplaceholder.typicode.com/posts', {
         method: 'POST',
         body: JSON.stringify({
            title: title,
            body: body,
            userId: Math.random().toString(36).slice(2),
         }),
         headers: {
            'Content-type': 'application/json; charset=UTF-8',
         },
      });
      let data = await response.json();
      setPosts((posts) => [data, ...posts]);
      setTitle('');
      setBody('');
   };

   const handleSubmit = (e) => {
      e.preventDefault();
      addPosts(title, body);
   };

   return (
      // ...
   );
};

export default App;
Войти в полноэкранный режим Выйти из полноэкранного режима

Обработка ошибок

В этом разделе мы рассмотрим, как обрабатывать ошибки как традиционно, так и с помощью async/await. Мы можем использовать данные ответа для обработки ошибок в Fetch API или использовать оператор try/catch при использовании async/await. Давайте рассмотрим, как мы можем сделать это традиционно в Fetch API:

const fetchPost = () => {
fetch('https://jsonplaceholder.typicode.com/posts?_limit=10')
   .then((response) => {
      if (!response.ok) {
         throw Error(response.statusText);
      }
      return response.json();
   })
   .then((data) => {
      console.log(data);
      setPosts(data);
   })
   .catch((err) => {
      console.log(err.message);
   });
};
Войти в полноэкранный режим Выход из полноэкранного режима

Подробнее об ошибках Fetch API вы можете прочитать здесь.

А для async/await мы можем использовать try и catch следующим образом:

const fetchPost = async () => {
   try {
      const response = await fetch(
         'https://jsonplaceholder.typicode.com/posts?_limit=10'
      );
      const data = await response.json();
      setPosts(data);
   } catch (error) {
      console.log(error);
   }
};
Войти в полноэкранный режим Выйти из полноэкранного режима

Потребление API с помощью Axios

Axios — это клиентская библиотека HTTP, основанная на обещаниях, которая упрощает отправку асинхронных HTTP-запросов к конечным точкам REST. В нашем случае такой конечной точкой является JSONPlaceholder Posts API, к которому мы будем делать запросы GET, POST и DELETE.

Установка и настройка экземпляра Axios

Axios, в отличие от Fetch API, не является встроенным, поэтому для его использования нам потребуется включить его в наш проект. Мы можем добавить Axios в наш проект, выполнив следующую команду:

npm install axios
Войти в полноэкранный режим Выйти из полноэкранного режима

После успешной установки мы можем приступить к созданию экземпляра, что необязательно, но рекомендуется, так как избавляет нас от ненужных повторений. Для создания экземпляра мы используем метод .create(), который можно использовать для указания такой информации, как URL и, возможно, заголовки:

import axios from "axios";

const client = axios.create({
   baseURL: "https://jsonplaceholder.typicode.com/posts" 
});
Войти в полноэкранный режим Выход из полноэкранного режима

Выполнение GET-запроса в React с помощью Axios

Для этого мы будем использовать экземпляр, который мы объявили ранее, и все, что мы сделаем, это установим параметры, если таковые имеются, и получим ответ в виде json по умолчанию. В отличие от метода Fetch API, здесь не требуется объявлять метод; мы просто прикрепляем метод к экземпляру и запрашиваем его.

useEffect(() => {
   client.get('?_limit=10').then((response) => {
      setPosts(response.data);
   });
}, []);
Вход в полноэкранный режим Выход из полноэкранного режима

Выполнение POST-запроса в React с помощью Axios

Как было сказано ранее, метод POST можно использовать для отправки данных в конечную точку; он функционирует аналогично запросу GET, с основным отличием в том, что требуется включить метод и опцию для удержания данных, которые мы отправляем:

const addPosts = (title, body) => {
   client
      .post('', {
         title: title,
         body: body,
      })
      .then((response) => {
         setPosts((posts) => [response.data, ...posts]);
      });
};
Войти в полноэкранный режим Выход из полноэкранного режима

Выполнение запроса DELETE в React с помощью Axios

Мы можем выполнять запросы на удаление с помощью метода delete, который получит id и удалит его из API, а также мы будем использовать метод filter, чтобы удалить его из пользовательского интерфейса, как мы это делали с методом Fetch API:

const deletePost = (id) => {
   client.delete(`${id}`);
   setPosts(
      posts.filter((post) => {
         return post.id !== id;
      })
   );
};
Вход в полноэкранный режим Выход из полноэкранного режима

Использование Async/Await в Axios

До сих пор мы видели, как делать запросы в Axios, используя синтаксис promise, но теперь давайте посмотрим, как можно использовать async/await, чтобы написать меньше кода и избежать цепочки .then().

Когда мы используем async/await, все наши запросы Axios будут выглядеть следующим образом:

import React, { useState, useEffect } from 'react';

const App = () => {
   const [title, setTitle] = useState('');
   const [body, setBody] = useState('');
   const [posts, setPosts] = useState([]);

   // GET with Axios
   useEffect(() => {
      const fetchPost = async () => {
         let response = await client.get('?_limit=10');
         setPosts(response.data);
      };
      fetchPost();
   }, []);

   // Delete with Axios
   const deletePost = async (id) => {
      await client.delete(`${id}`);
      setPosts(
         posts.filter((post) => {
            return post.id !== id;
         })
      );
   };

   // Post with Axios
   const addPosts = async (title, body) => {
      let response = await client.post('', {
         title: title,
         body: body,
      });
      setPosts((posts) => [response.data, ...posts]);
   };

   const handleSubmit = (e) => {
      e.preventDefault();
      addPosts(title, body);
   };

   return (
      // ...
   );
};

export default App;
Войти в полноэкранный режим Выход из полноэкранного режима

Обработка ошибок

Для запросов Axios на основе обещаний мы можем использовать методы.then() и.catch (), но для async/await мы можем использовать блок try...catch. Это очень похоже на то, как был реализован Fetch API, блок try...catch будет выглядеть следующим образом:

const fetchPost = async () => {
   try {
      let response = await client.get('?_limit=10');
      setPosts(response.data);
   } catch (error) {
      console.log(error);
   }
};
Вход в полноэкранный режим Выход из полноэкранного режима

Подробнее об обработке ошибок в Axios вы можете прочитать здесь.

Fetch API против Axios

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

Axios Fetch
Axios — это отдельный пакет стороннего разработчика, который просто установить. Fetch встроен в большинство современных браузеров; установка как таковая не требуется.
Axios использует свойство data. Fetch использует свойство body.
Данные Axios содержат объект. Тело Fetch должно быть структурировано.
Если статус равен 200, а statusText — ‘OK’, запрос Axios принят. Запрос Fetch считается нормальным, если объект ответа содержит свойство ok.
Axios выполняет автоматические преобразования данных JSON. Fetch — это двухэтапный процесс при работе с данными JSON: во-первых, выполнение фактического запроса; во-вторых, вызов метода .json() в ответе.
Axios позволяет отменить запрос и таймаут запроса. Fetch этого не делает.
Axios имеет встроенную поддержку прогресса загрузки. Fetch не поддерживает прогресс загрузки.
Axios имеет широкую поддержку браузеров. Если статус равен 200, а статусТекст — ‘OK’, запрос Axios принят. Fetch совместим только с Chrome 42+, Firefox 39+, Edge 14+ и Safari 10.1+. (Это известно как обратная совместимость).

Заключение

В этом руководстве мы узнали, как использовать REST API в react с помощью Fetch API или Axios. Это поможет вам начать работу с потреблением API в React, а затем вы сможете выполнять более уникальные операции с данными и манипуляции с API.

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