242 lines
10 KiB
Markdown
242 lines
10 KiB
Markdown
# Лабораторная работа №F4 - Взаимодействие с API (Axios)
|
||
|
||
## Цель работы
|
||
|
||
- Освоение взаимодействия между fronend и backend в веб-приложениями посредством технологии `axios`.
|
||
- Получение навыков формирования макета RESTful API при помощи технологии `json-server`.
|
||
- Освоение технологии `Postman` для работы с API, основанным на протоколе HTTP(S).
|
||
|
||
## Ход работы
|
||
|
||
1. Проверить и при необходимости исправить код описания формы ввода данных в приложении из [lwF3](../lwF3/README.md).
|
||
2. Развернуть API-сервер на основе `json-server` рядом с frontend-приложением.
|
||
3. Развернуть ПО Postman и выполнить CRUD-запросы на API-сервере (backend).
|
||
4. Подключить к frontend пакет `axios`.
|
||
5. Добавить в обработчик отправки формы вызов метода добавления данных в API-сервер при помощи axios.
|
||
6. Убедиться через Postman и через блокнот, что данные корректно пришли с frontend на backend.
|
||
|
||
## Проверка формы ввода
|
||
|
||
При использовании Consta Design, убедитесь, что все текстовые поля записывают значение во внутреннее состояние формы.
|
||
|
||
Если используете собственные обёртки, пропсы `value` и `onChange` "перекидывать" из компонентов Consta Design далее.
|
||
|
||
Пример формы БЕЗ компонентов-обёрток (у Вас должно быть с "обёртками"):
|
||
|
||
```tsx
|
||
export const FeedbackForm = () => {
|
||
const [nameValue, setNameValue] = useState<string | null>(null);
|
||
const [textValue, setTextValue] = useState<string | null>(null);
|
||
|
||
const handleSend = () => {
|
||
/* TODO: логика по отправке данных на сервер. */
|
||
};
|
||
|
||
return (
|
||
<Theme preset={presetGpnDefault}>
|
||
<TextField
|
||
onChange={setNameValue}
|
||
value={nameValue}
|
||
type="text"
|
||
label="Имя"
|
||
placeholder="Как Вас зовут?"
|
||
/>
|
||
<TextField
|
||
onChange={setTextValue}
|
||
value={textValue}
|
||
type="textarea"
|
||
rows={5}
|
||
label="Сообщение"
|
||
placeholder="Напишите, что Вы думаете о нас..."
|
||
/>
|
||
<Button label="Отправить" onClick={handleSend} />
|
||
</Theme>
|
||
);
|
||
}
|
||
```
|
||
|
||
Пример обёртки над текстовым полем:
|
||
|
||
```jsx
|
||
import {
|
||
TextField as ConstaTextField,
|
||
TextFieldPropOnChange,
|
||
TextFieldPropValue,
|
||
} from "@consta/uikit/TextField";
|
||
|
||
interface TextFieldProps {
|
||
onChange: TextFieldPropOnChange;
|
||
value: TextFieldPropValue;
|
||
label: string;
|
||
placeholder: string;
|
||
}
|
||
|
||
export const TextField = (props: TextFieldProps) => (
|
||
<ConstaTextField
|
||
type="text"
|
||
onChange={props.onChange}
|
||
value={props.value}
|
||
label={props.label}
|
||
placeholder={props.placeholder}
|
||
/>
|
||
);
|
||
```
|
||
|
||
Если же вы используете обычные элементы `input`, `textarea` и т.п., тогда надо использовать их в controlled-режиме (подробнее о режимах полей ввода [можете почитать в документации](https://react.dev/reference/react-dom/components/input#controlling-an-input-with-a-state-variable)).
|
||
Например, так:
|
||
|
||
```jsx
|
||
<input
|
||
onChange={(e) => setNameValue(e.target.value)}
|
||
value={nameValue}
|
||
type="text"
|
||
placeholder="Как Вас зовут?"
|
||
/>
|
||
<textarea
|
||
value={textValue}
|
||
onChange={(e) => setTextValue(e.target.value)}
|
||
placeholder="Напишите, что Вы думаете о нас..."
|
||
></textarea>
|
||
```
|
||
|
||
Только обратите внимание, что необходимо изменить тип в переменных состояния, отвечающих за значения данных на форме, т.к. `string | null` уже не подходит.
|
||
|
||
## Установка сервера json-server
|
||
|
||
Создайте каталог рядом с react-приложением.
|
||
|
||
Создайте в нём файл `db.json` с содержимым:
|
||
|
||
```json
|
||
{
|
||
"feedback": []
|
||
}
|
||
```
|
||
|
||
> Замените `feedback` на кодовое название сущности, к которой относится ваша форма.
|
||
> Например, `order` для заказа, `thread` для ветви обсуждения и т.п.
|
||
|
||
Запустите в консоли в созданном каталоге команду `npx json-server db.json`.
|
||
|
||
Примерный вывод:
|
||
|
||
```
|
||
JSON Server started on PORT :3000
|
||
Press CTRL-C to stop
|
||
Watching db.json...
|
||
|
||
♡( ◡‿◡ )
|
||
|
||
Index:
|
||
http://localhost:3000/
|
||
|
||
Static files:
|
||
Serving ./public directory if it exists
|
||
|
||
Endpoints:
|
||
No endpoints found, try adding some data to db.json
|
||
|
||
Endpoints:
|
||
http://localhost:3000/feedback
|
||
```
|
||
|
||
Запомните последнюю ссылку, она нам понадобится позже.
|
||
|
||
## Проверка работы API при помощи утилиты Postman
|
||
|
||
Postman – утилита для работы с API-интерфейсами в стиле REST (популярен в web).
|
||
|
||
Страница для скачивания: <https://www.postman.com/downloads/>.
|
||
|
||
Продолжите запуск без учётной записи (2 раза надо об этом сказать).
|
||
|
||
Далее необходимо сделать процедуры CRUD.
|
||
Это сокращение от Create, Read, Update, Delete.
|
||
|
||
Согласно документации json-server доступны следующие методы API (на примере ресурса `posts`):
|
||
|
||
```
|
||
GET /posts
|
||
GET /posts/:id
|
||
POST /posts
|
||
PUT /posts/:id
|
||
PATCH /posts/:id
|
||
DELETE /posts/:id
|
||
```
|
||
|
||
Попробуем выполнить запросы по аналогии с feedback.
|
||
|
||
Создание:
|
||
|
||

|
||
|
||
Просмотр списка:
|
||
|
||

|
||
|
||
Просмотр подробностей:
|
||
|
||

|
||
|
||
Обновление:
|
||
|
||

|
||
|
||
Удаление:
|
||
|
||

|
||
|
||
При этом в файле `db.json` всё время будут происходить изменения, инициированные запросами к API.
|
||
|
||
## Подключение axios к frontend
|
||
|
||
Axios – технология для вызова API-методов (по аналогии с Postman) для frontend-приложений.
|
||
|
||
Устанавливается при помощи команды `npm install axios`.
|
||
|
||
Использовать axios необходимо в функции `handleSend`.
|
||
|
||
Сделайте это самостоятельно, используя следующие требования/подсказки:
|
||
|
||
- Метод `handleSend` удобно поментить `async`.
|
||
В этом случае вызов `post(endpont, data)` из библиотеки `axios` можно пометить как `await`.
|
||
- Собирать объект для отправки на бекенд надо прямо в методе `.post`, а не через отдельную контанту/переменную.
|
||
- При ошибке (например, сервер недоступен) метод `axios.post` выбрасывает исключение.
|
||
Его надо ловить и каким-то образом показывать на экран.
|
||
Для этого можно использовать функцию `alert` или ошибку из пакета `react-toastify` (ставится отдельно).
|
||
- В случае успеха надо также использовать отображение данных через `alert` или `toast`.
|
||
- Метод не должен ничего выводить в консоль. Только для отладки. Код вывода в консоль перед сдачей лабораторной работы должен быть удалён.
|
||
|
||
Пример отправки данных на сервер, который НЕ подходит под требования, но который работает:
|
||
|
||
```jsx
|
||
import axios from "axios";
|
||
|
||
const handleSend = () => {
|
||
console.log(nameValue, textValue);
|
||
const data = {
|
||
name: nameValue,
|
||
text: textValue,
|
||
};
|
||
axios
|
||
.post("http://localhost:3000/feedback", data)
|
||
.then(() => alert("Данные отправлены, спасибо!"));
|
||
};
|
||
```
|
||
|
||
## Проверка работы
|
||
|
||
Убедитесь, что после отправки формы в файле `db.json` появляются указанные в полях ввода данные.
|
||
Дополнительно убедитесь, что через Postman в методе GET также возвращаются эти же данные.
|
||
|
||
Убедитесь, что при отключении json-server приложение React начинает выдавать ошибку отправки, правда спустя какое-то время (тайм-аут).
|
||
|
||
## Дополнительные улучшения
|
||
|
||
> За которые возможны доп. баллы.
|
||
|
||
1. Вместо alert использовать react-toastify с правильно подобранными типами уведомлений: для ошибки - ошибка, для успеха - успех.
|
||
2. Необходимо на время отправки данных блокировать (disabled) кнопку отправки и поля ввода.
|
||
3. Если при отправке формы был получен успешный ответ от API, получать и выводить `id` созданной сущности.
|
||
Например, `Обращение №4ba0 зарегистрировано, спасибо!`
|