Научитесь выполнять операции CRUD в нескольких строках кода с помощью таблицы материалов.

Привет, ребята, добро пожаловать в мой первый учебник react.js 😊 Я собираюсь показать вам, как выполнять операции CRUD в React, создав простое веб-приложение для управления пользователями. Мы собираемся использовать пакет Material-table с удаленными данными (т.е. данными из RESTful API).

На видео ниже показано приложение, которое мы будем разрабатывать.

Пакет Material-table расширяет стандартную таблицу из Material-ui, предоставляя множество интересных готовых функций, таких как панель поиска, кнопка добавления, разбиение на страницы и т. Д. Использование таблицы материалов обеспечивает супер-бесшовное средство выполнения операций CRUD в react.js. Поверьте мне, вы не захотите испытывать стресс от использования традиционных форм для операций CRUD после того, как узнаете, насколько легко это сделать с этим замечательным пакетом. Хорошо, достаточно разговоров. Давайте начнем.

Я предполагаю, что вы немного знакомы с основными концепциями реагирования (такими как состояния), Javascript и RESTful API. Кроме того, ноу-хау Material UI было бы здорово, но не обязательно.

Чтобы начать использовать таблицу материалов, убедитесь, что вы установили ее, как показано ниже:

npm install material-table --save
npm install @material-ui/core --save
or (if you using yarn)
yarn add material-table
yarn add @material-ui/core

В таблице материалов используются значки material-ui, поэтому убедитесь, что вы установили значки Material-ui, как показано ниже:

npm install @material-ui/icons --save
yarn add @material-ui/icons

Я также использовал компонент Material-ui Alert для уведомления в случае ошибки. Нам нужно установить его, используя команду ниже:

npm install @material-ui/lab --save
yarn add @material-ui/lab

Ой, чуть не забыл о пакете axois, который использовался для инициации запроса API. Установите пакет, как показано ниже:

npm install axios --save
yarn add axios

Теперь давайте посмотрим на исходные коды, когда мы установили необходимые пакеты. Полный исходный код проекта доступен на github, который вы можете скачать и опробовать. Я собираюсь сосредоточиться здесь только на соответствующих разделах кода.

Backend - удаленный источник данных

Это приложение полагается на бесплатный онлайн-REST API, чтобы абстрагироваться от сложности создания такого API самостоятельно, поскольку это не является основной темой учебника. Для этого мы будем использовать https://reqres.in/. Он предоставляет конечные точки API, которые позволяют нам делать (связанные с пользователями) запросы API, такие как POST (для создания записи, в нашем случае: создать нового пользователя), GET (для выборки записей), PUT / PATCH (для обновления записи), УДАЛИТЬ (как следует из названия) и т. Д. Я бы посоветовал вам посетить этот сайт и ознакомиться с различными возможными вызовами API. Перейдем к веб-интерфейсу.

Фронтенд - Reactjs, UI / таблица материалов

React Material UI предоставляет нам множество компонентов (Alert, Tables, Navbar и т. Д.) Для создания потрясающих пользовательских интерфейсов в React - без написания ни единой строчки кода CSS. Другой популярный UI-фреймворк - react-bootstrap (да, это та же самая старая бутстрап-фреймворк, перестроенная для реакции). Как было сказано ранее, Material-table расширяет стандартную таблицу Material-UI дополнительными интересными функциями. Давайте начнем с нашей таблицы пользователей.

В таблицах обычно есть строки и столбцы. Нам нужно будет определить столбцы и строки (данные) для нашей таблицы, как показано ниже:

var columns = [
{title: "id", field: "id", hidden: true},
{title: "Avatar", render: rowData => <Avatar maxInitials={1} size={40} round={true} name={rowData === undefined ? " " : rowData.first_name} />  },
{title: "First name", field: "first_name"},
{title: "Last name", field: "last_name"},
{title: "email", field: "email"}
]
const [data, setData] = useState([]); //table data
//for error handling
const [iserror, setIserror] = useState(false)
const [errorMessages, setErrorMessages] = useState([])

Из приведенного выше фрагмента кода в нашей таблице будут столбцы идентификаторов, имени, фамилии, электронной почты и аватара. Давайте посмотрим на пример данных JSON, которые мы получим от RESTful API. Это показано ниже:

//JSON data from RESTful API
"user": 
 {
    "id": 2,
    "email": "[email protected]",
    "first_name": "Janet",
    "last_name": "Weaver",
    "avatar": " "
 }

Вы заметили, что ключи данных JSON (id, email,…) точно соответствуют столбцам таблицы - атрибутам поля (id, email,…)? Это очень важно, так как Material-table использует это для правильного отображения данных из нашего API, то есть сопоставления данных API со столбцами таблицы. Надеюсь, вы уловили идею?

Переменная data будет хранить данные нашей таблицы в переменной состояния. Приложение (компонент на языке react) повторно отображает (реагирует) при изменении состояния (используя метод set, то есть setData в нашем примере). Другие переменные состояния используются для обработки ошибок. Мы коснемся их позже.

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

useEffect(() => {
  api.get("/users")
    .then(res => {
      setData(res.data.data)
    })
    .catch(error=>{
      setErrorMessage(["Cannot load user data"])
      setIserror(true)
    })
}, [])

Мы получаем список пользователей внутри хука реакции useEffect - функция useEffect запускается каждый раз, когда визуализируется функциональный компонент, например. при обновлении страницы или изменении данных состояния (в этом случае данные состояния необходимо включить в массив useEffect). API отвечает на наш инициированный запрос GET списком данных пользователей. Затем мы используем метод setData для изменения состояния объекта данных. Теперь переменная данных содержит список пользователей вместо пустого массива. С другой стороны, если возникает ошибка, мы предупреждаем пользователя. Это было легко, правда? 😊

Итак, у нас есть данные, и самое время отобразить их в таблице.

<MaterialTable
  title="User list from API"
  columns={columns}
  data={data}
  icons={tableIcons}
  editable={{
    onRowUpdate: (newData, oldData) =>
      new Promise((resolve) => {
        handleRowUpdate(newData, oldData, resolve);
  }),
  onRowAdd: (newData) =>
    new Promise((resolve) => {
      handleRowAdd(newData, resolve)
    }),
  onRowDelete: (oldData) =>
    new Promise((resolve) => {
      handleRowDelete(oldData, resolve)
    }),
  }}
/>

Приведенный выше фрагмент кода отвечает за отображение таблицы. Он использует компонент «Таблица материалов». Указываем заголовок, столбцы и данные (список пользователей). Мы также включаем список значков, необходимых для работы компонента. Эти значки включают стрелки (для разбивки на страницы), значки поиска, редактирования, удаления и т. Д. Если мы запустим приложение, отобразится снимок экрана ниже.

Таким образом, мы позаботимся о R операциях C R UD. Перейдем к операции C reate, т. Е. Добавлению нового пользователя. Обратите внимание, что приведенный выше код включает реквизиты для выполнения других операций CRUD (создание, обновление и удаление). Свойство onRowAdd создает новый объект Promise (обещание возвращает значение в будущем. Это позволяет обрабатывать асинхронные события - подробнее здесь). Объект обещания вызывает функцию handleRowAdd (). В приведенном ниже фрагменте кода представлена ​​реализация функции.

const handleRowAdd = (newData, resolve) => {
  //validation
  let errorList = []
  if(newData.first_name === undefined){
    errorList.push("Please enter first name")
  }
  if(newData.last_name === undefined){
    errorList.push("Please enter last name")
  }
  if(newData.email === undefined || validateEmail(newData.email) === false){
    errorList.push("Please enter a valid email")
  }
  if(errorList.length < 1){ //no error
    api.post("/users", newData)
      .then(res => {
        let dataToAdd = [...data];
        dataToAdd.push(newData);
        setData(dataToAdd);
        resolve()
        setErrorMessages([])
        setIserror(false)
     })
     .catch(error => {
        setErrorMessages(["Cannot add data. Server error!"])
        setIserror(true)
        resolve()
      })
  }else{
    setErrorMessages(errorList)
    setIserror(true)
    resolve()
  }
}

Функция настолько проста, насколько кажется. Сначала мы делаем некоторые проверки, чтобы убедиться, что пользователь заполнил все обязательные поля. Затем мы отправляем POST-запрос с данными, которые хотим добавить (например, newData). Затем мы можем продолжать делать что-то еще (да, именно здесь появляется Promise - подумайте о многопоточности), пока мы не получим ответ от сервера (API). Если запрос POST был успешным, мы обновляем данные состояния с помощью функции setData () и помечаем обещание как разрешенное (см. Функцию then). В противном случае мы предупреждаем пользователя об ошибке.

Давайте теперь посмотрим, как обновить данную строку в нашей таблице. Для этого мы вызываем функцию handleRowUpdate (…). Его реализация представлена ​​ниже.

const handleRowUpdate = (newData, oldData, resolve) => {
  //validation
  .....
  if(errorList.length < 1){
    api.patch("/users/"+newData.id, newData)
      .then(res => {
        const dataUpdate = [...data];
        const index = oldData.tableData.id;
        dataUpdate[index] = newData;
        setData([...dataUpdate]);
        resolve()
        setIserror(false)
        setErrorMessages([])
      })
      .catch(error => {
        setErrorMessages(["Update failed! Server error"])
        setIserror(true)
        resolve()
    })
  }else{
    setErrorMessages(errorList)
    setIserror(true)
    resolve()
  }
}

Я почти уверен, что вы сможете понять, что делает эта функция. Мы инициируем запрос PATCH, который является вызовом API для обновления данных. Обратите внимание, что мы передаем id (в нашем случае идентификатор пользователя) в URL-адресе запроса, чтобы API знал, какую запись нужно обновить. Если сервер сможет успешно удовлетворить наш запрос, мы получим ответ. Затем мы обновляем наше состояние. В противном случае мы предупреждаем пользователя об ошибках. Проверка формы пропускается, так как она аналогична предыдущему случаю.

Итак, это касается наших операций C reate R ead U pdate. Теперь у нас осталась операция D elete. Давайте посмотрим на это дальше.

const handleRowDelete = (oldData, resolve) => {
  api.delete("/users/"+oldData.id)
    .then(res => {
      const dataDelete = [...data];
      const index = oldData.tableData.id;
      dataDelete.splice(index, 1);
      setData([...dataDelete]);
      resolve()
    })
    .catch(error => {
      setErrorMessages(["Delete failed! Server error"])
      setIserror(true)
      resolve()
    })
}

Приведенный выше фрагмент кода предоставляет функцию для обработки операции удаления. Этот метод очень похож на предыдущий (PATCH). Разница здесь в том, что мы инициируем запрос DELETE.

Резюме

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

Таблица материалов великолепна, и мне нравятся такие нестандартные функции, как (простота создания, обновления, удаления записей или строк), которые она предоставляет. Я лично использовал этот пакет для кода производственного уровня. Еще одна интересная особенность пакета - его очень легко настроить. Вы можете заменить столбцы средством выбора даты и времени в пользовательском интерфейсе материала или изменить значки (удалить, отредактировать, найти). При этом таблица материалов особенно хороша для отображения табличных данных.

Надеюсь, вы кое-что узнали из этого урока.

Не стесняйтесь скачать / клонировать исходный код проекта на Github.

Ознакомьтесь с моими другими уроками Сетевое программирование на Python, если вы этого не сделали…

Удачи тебе от меня!