Введение в JSON Server (часть II)

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

Предварительные условия

  • Чтобы следовать этой статье, необходимы предварительные знания React Hook, React Suspense API и JSON Server.
  • Вот репозиторий GitHub (инструкции находятся в файле readme)

Введение

В этой части мы собираемся применить на практике некоторые типы запросов (POST, GET, PUT, PATCH и DELETE).
Прежде чем мы начнем, в первой части мы смогли получить данные из нашей базы данных.json, играя с URL. В этой части мы будем делать то же самое, но вместо того, чтобы вносить изменения в URL, мы напишем несколько кодов.

Примечание: мы используем API react Suspense для получения данных. Подробнее об этом вы можете прочитать здесь, так как это не входит в рамки данной статьи.

GET-запрос

Приложение запущено на localhost:3000
а сервер на порту localhost:7000;

ПОЛУЧИТЬ ВСЕ ИТЕМЫ
В репозитории вашего проекта перейдите к файлу fetchFici.js в разделе web-client/src/page/

Мы собираемся создать функцию fetch для получения наших данных с сервера JSON.
В первой строке над типом wrapPromise введите этот код:

const readAllFici = () => {
    return fetch("http://localhost:7000/data")
        .then(res => res.json())
        .catch(err => console.log(err))
}
Войти в полноэкранный режим Выйти из полноэкранного режима

В файле createRousource добавьте readAllFici() в wrapPromise следующим образом:

export const createResource = () => {
    return {
        data: wrapPromise(ReadAllFici())
    }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

В первом фрагменте мы создали функцию и назвали ее
readAllFici, в качестве первого параметра мы передали json url сервера, после чего получили ответ от сервера.

В следующем фрагменте мы передаем функцию fetch в createResource, что является частью структуры использования react Suspense.

Далее, все в той же папке перейдите к index.jsx
мы импортируем createResource и используем его в нашем компоненте Screen следующим образом:

import { createResource } from './fetchFici';

const resource = createResource();
return (
   <Suspense fallback={<Spinner />}>
      <Screen resource={ressource} />
   </Suspense>
);
Вход в полноэкранный режим Выйти из полноэкранного режима

В файл screen.jsx добавьте этот фрагмент:

const Screen = ({ resource }) => {
    const ficiData = resource.data.read()

    const displayFici = ficiData.map((item, index) => {
        return (
             ...
       )
...
Вход в полноэкранный режим Выйти из полноэкранного режима

В приведенном выше фрагменте мы получаем данные, отправленные сервером.
Чтобы увидеть результат в браузере, обновите страницу.


Мы получили все элементы с сервера и передали их внутрь компонента.

ПОЛУЧЕНИЕ ОТДЕЛЬНОГО ЭЛЕМЕНТА
Чтобы получить один элемент, мы изменим fetch url на "/{идентификатор элемента}".
Давайте реализуем это.

Сначала создадим новую функцию для получения элемента на основе id:

const readOneItem = (id) => {
    return fetch(`http://localhost:7000/data/${id}`)
        .then(res => res.json())
        .catch(err => console.log(err))
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Далее, ниже createResource мы создадим новую стрелочную функцию, такую же, как createResource, но с параметром, и этот параметр будет получен readOneItem.

export const createResourceOnePost = (id) => {
    return {
        data: wrapPromise(readOneItem(id))
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Далее в singlePost.jsx у нас есть два компонента, один из которых получает данные и передает их через компонент, а другой отображает их. Перед этим нам нужно получить id отдельного элемента. В нашем случае мы использовали react-router-dom (вы можете посмотреть в App.jsx, как мы настроили маршрутизацию).
Во втором компоненте мы собираемся получить параметр id из URL, для этого импортируем useParams() и получим id:

import { useParams } from 'react-router-dom'

const { id } = useParams()
Вход в полноэкранный режим Выход из полноэкранного режима

Импортируем createResourceOnePost и вызовем первый компонент внутри Suspense, который принимает ressource в качестве параметра.

import { createResourceOnePost } from './fetchFici'
const resource = createResourceOnePost(id)
 return (
        <div className='border rounded-md bg-zinc-800 border-white p-4'>
            <p className='text-center text-3xl font-mono'>Fici Game</p>
            <Suspense fallback={<Spinner />}>
                <LoadData resource={resource} />
            </Suspense>
        </div>
    )
Вход в полноэкранный режим Выход из полноэкранного режима

Внутри дочернего компонента используем данные, переданные в родительском компоненте.

const LoadData = ({ resource }) => {
    const ficiData = resource.data.read()

    return (
        <div className='border bg-gray-900 flex flex-col space-y-4 justify-center items-center border-white h-80 m-4'>
            <p className="p-4 font-mono text-lg">{ficiData.name}</p>
            <span className='text-9xl shadow-2xl rounded-full'>{ficiData.symbol}</span>
        </div>
    )
    }
Войти в полноэкранный режим Выход из полноэкранного режима

Последнее, что нам нужно сделать, это перейти к определенному элементу.
В файле screen.jsx создайте onClick внутри displayFici

import { useNavigate } from 'react-router-dom';

const navigate = useNavigate()
const displayFici = ficiData.map((item, index) => {
        return (

            <tr className='border-b border-gray-500 cursor-pointer' onClick={() => {
                navigate(`/${item.id}`)
            }} key={index}>
                <td className='p-2'>{item.id}</td>
                <td className='p-2 text-center'>{item.name}</td>
                <td className='p-2'>
                    <span className='text-xl'>{item.symbol}</span>
                </td>
            </tr>

        )
    })
Войти в полноэкранный режим Выйти из полноэкранного режима

Вывод

ПОСТ МЕТОД

Давайте добавим третий элемент в наш список элементов.
Для этого нам нужно создать функцию, такую же, как для запроса get, но вместо получения мы будем посылать (отправлять) данные на наш JSON-сервер.
Так что давайте создадим ее в fetchFici.js

export const postItem = () => {
    const doc = {
        name: 'Tornado',
        symbol: '🌪️'
    }
    return fetch('http://localhost:7000/data', {
        method: "POST",
        body: JSON.stringify(doc),
        headers: { 'content-Type': 'application/json' }
    })
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Мы создали объект doc, в который вручную передали элемент, который мы хотим добавить в наш список, затем, чтобы добавить этот элемент в наш database.json, нам нужно выполнить fetch, первым параметром будет URL, на этот раз он получит второй параметр, который является объектом внутри, мы передаем метод, который в нашем случае является POST, тело и заголовки.

Мы делаем то же самое, что и для запроса get.
Мы импортируем функцию в компонент screen.jsx, и она будет выполняться при нажатии на кнопку.

import { postItem } from './fetchFici';

<div>
     <p className='text-center p-2'>➕</p>
     <div className='text-center'>
        <button className='bg-sky-700 rounded-lg w-20 p-2' onClick={() => { postItem() }}>🌪️</button>
        <p className='font-mono'>Tornado</p>

     </div>
</div>
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь, если вы нажмете на кнопку и обновите страницу, вы увидите, что элемент был добавлен (подробнее об useEffecf читайте здесь).


Если вы посмотрите в нашем файле database.json, то вместо 4 у нас теперь 5 элементов. Пока все хорошо, теперь вы знаете, как получать и отправлять данные с сервера JSON, теперь давайте посмотрим, как обновлять и удалять данные.

ОБНОВЛЕНИЕ И УДАЛЕНИЕ ДАННЫХ

Обновление - это почти то же самое, что и другие типы запросов, мы просто меняем метод на PUT или PATCH вместо POST.
Примечание: Разница между PUT и PATCH заключается в том, что при использовании PUT вы должны указать все свойства внутри тела объекта, а если вам нужно обновить только одно свойство, вы можете использовать запрос PATCH.

Итак, создайте новую функцию и назовите ее updatItem в fetchFici.js.

export const updateItem = (id, body) => {
    return fetch(`http://localhost:7000/data/${id}`, {
        method: "PATCH",
        body: JSON.stringify(body),
        headers: { 'content-Type': 'application/json' }

    })
}
Вход в полноэкранный режим Выйти из полноэкранного режима

В приведенном выше коде мы передали два параметра: id для элемента, который мы хотим обновить, и новое имя.

Теперь в singlePost.jsx добавим несколько строк кода.

import { updateItem } from './fetchFici'
import React, { useState } from 'react'


const LoadData = ({ resource }) => {
    const { id } = useParams();
   const [text, setText] = useState('');
    return (
   ...
            <span></span>
            <form onSubmit={updateHandler} className="flex flex-col">
                <input className='text-gray-700 text-center rounded-lg p-1' type="text" placeholder={ficiData?.name} value={text} onChange={(e) =>
                    setText(e.target.value)
                } />
                <button type='submit' className='p-4 bg-zinc-800 rounded-b-lg'>UPDATE</button>
            </form>
    )
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Вывести


Теперь, если вы измените название и нажмете обновить, а затем обновите страницу, вы увидите изменения; в моем случае я обновил Air на Vortex.

УДАЛИТЬ ЭЛЕМЕНТ

Теперь давайте посмотрим, как удалить элемент.
Вы уже знаете, как создать функцию запроса,
создайте функцию, аналогичную updateItem
затем удалите все тело объекта, так как оно не нужно, затем измените метод запроса на DELETE, не забудьте передать параметр id, вам нужно знать, какой элемент вы хотите удалить из списка элементов.

import { deleteItem } from './fetchFici';

export const deleteItem = (id) => {
    return fetch(`http://localhost:7000/data/${id}`, {
        method: "DELETE"
    })
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Далее добавим немного кода в файл screen.jsx

  <td>
      <button className='p-1' onClick={() => {
                        deleteItem(item.id)
                    }}><TbTrash className='text-red-600'/>
     </button>
</td>
Вход в полноэкранный режим Выйти из полноэкранного режима

Мы импортировали deleteItem, внутри displayFici мы добавили новый тег td с кнопкой, передали deleteItem в onClick.

Вывод

Нажмите на один элемент, затем обновите страницу и вы увидите, что элемент был удален.

Заключение

Мы подошли к концу нашего руководства, мы увидели некоторые типы запросов, которые полезны для тестирования конечных точек при создании прототипов.
Для тех типов, которые были рассмотрены в первой части, я настоятельно рекомендую вам пойти и попробовать реализовать их, и дайте мне знать в комментариях, если вы столкнетесь с какими-либо трудностями при их реализации, я буду рад помочь.
Если вы нашли эту статью полезной, не забудьте поделиться ею со своими друзьями.

полный исходный код GitHub repo
Узнать больше о React Suspense API можно здесь

До следующего раза, берегите себя.

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