풀 스택 React 및 Node.js - HTTP POST

이제 클라이언트에서 서버로 데이터를 POST할 것입니다.

이전에는 데이터를 가져오기 위한 HTTP GET 요청을 사용했습니다. 데이터를 추가하기 위해 HTTP POST를 사용합니다.

먼저 노드 서버에 몇 가지 작은 변경 사항을 적용해야 합니다.

note.controller.js를 다음과 같이 편집합니다.

const note = {
  id: 1,
  title: 'A Note',
  content: 'Lorem ipsum dolor sit amet',
  author: 'neohed',
  lang: 'en',
  isLive: true,
  category: '',
}

async function getNote(req, res) {
  res.json({ note });
}

async function postNote(req, res) {
  const {body} = req;
  const {id, title, content, author, lang, isLive, category} = body;

  console.log('Server received data:');
  console.log({id, title, content, author, lang, isLive, category})

  res
    .status(200)
    .json({
      message: 'Ok'
    })
}

module.exports = {
  getNote,
  postNote
}


새 기능postNote을 추가했습니다. 아직 DB가 없기 때문에 데이터를 수신했음을 증명하기 위해 데이터를 로그아웃하기만 하면 됩니다.

다음으로 route/index.js를 다음과 같이 편집합니다.

const express = require('express');
const noteRouter = express.Router();
const noteController = require('../controllers/note.controller');

noteRouter.get('', noteController.getNote);
noteRouter.post('', noteController.postNote);

const routes = app => {
  app.use('/note', noteRouter);
};

module.exports = routes


새 컨트롤러 메서드noteController.postNotegetNote와 동일한 엔드포인트에 마운트했습니다. 둘 다 동일한 URL에서 액세스됨/note
이것이 RESTful 아키텍처입니다. REpresentational State Transfer의 약자입니다. 요점은 우리가 사용하는 URL 끝점 또는 세그먼트가 엔터티를 나타내고 HTTP 동사(예: GET 또는 POST)가 작업을 나타낸다는 것입니다! 개체 엔터티는 note이므로 URL 끝점도 모든 작업에 대해 note입니다. GET, POST 및 이후 DELETE 등과 같은 다른 작업을 구별하기 위해 가져오기 요청에서 보내는 HTTP 동사를 사용합니다.

특정 익스프레스 라우터 기능.get().post() 및 이후 버전.delete()을 사용하므로 익스프레스는 /note URL 끝점에 대한 HTTP GET 요청이 수신되면 .getNote로 라우팅되어야 하고 언제 HTTP POST가 수신되면 라우팅되어야 함.postNote()
RESTful 아키텍처를 따르면 서버 API가 단순하고 깔끔해집니다. URL 세그먼트와 HTTP 동사의 조합을 사용하여 클라이언트와 서버 간의 대화를 설계하면 간단하고 표현력이 풍부한 표현이 가능합니다.

다음으로 반응 클라이언트를 업데이트해야 합니다.

먼저 약간의 리팩토링. strings.js라는 반응 클라이언트에 새 파일을 만들고 다음 코드를 붙여넣습니다.

const isNullOrUndefined = prop => prop === null
  || prop === undefined;
const isEmptyString = prop => isNullOrUndefined(prop)
  || prop === '';
const capitalize = word =>
  word.charAt(0).toUpperCase() +
  word.slice(1).toLowerCase();

function titleFromName(name) {
  if (isEmptyString(name)) {
    return '';
  }

  return name.split(/(?=[A-Z])|\s/).map(s => capitalize(s)).join(' ')
}

export {
  isNullOrUndefined,
  isEmptyString,
  capitalize,
  titleFromName,
}


다음으로 Form.js를 다음과 같이 편집합니다.

import React from 'react';
import InputLabel from "./InputLabel";
import {isEmptyString, titleFromName} from "./strings";
import './form.css'

const Form = ({entity, onSubmitHandler}) => {
  return (
    <form onSubmit={e => {
      const form = e.target;
      const newEntity = Object.values(form).reduce((obj, field) => {
        if (!isEmptyString(field.name)) {
          obj[field.name] = field.value
        }

        return obj
      }, {})

      onSubmitHandler(newEntity);

      e.stopPropagation();
      e.preventDefault()
    }}>
      {
        Object.entries(entity).map(([entityKey, entityValue]) => {
          if (entityKey === "id") {
            return <input
              type="hidden"
              name="id"
              key="id"
              value={entityValue}
            />
          } else {
            return <InputLabel
              id={entityKey}
              key={entityKey}
              label={titleFromName(entityKey)}
              type={
                typeof entityValue === "boolean"
                  ? "checkbox"
                  : "text"
              }
              value={entityValue}
            />
          }
        })
      }
      <button
        type="submit"
      >
        Submit
      </button>
    </form>
  );
};

export default Form;


문자열 유틸리티 함수를 제거하는 것 외에 주요 변경 사항은 모든 양식 필드를 가져오고 개체의 속성 및 값으로 이름 및 값 쌍을 추가한 다음 해당 개체를 이벤트 처리기 매개 변수에 전달하는 양식 onSubmit 이벤트 처리기를 추가하는 것입니다.

다음으로 AddEditNote.js를 편집하여 이 새onSubmitHandler 매개변수를 구현합니다.

이 코드를 AddEditNote.js에 붙여넣습니다.

import React, {useState, useEffect} from 'react';
import RenderData from "./RenderData";
import Form from './Form';

const AddEditNote = () => {
  const [note, setNote] = useState({});

  useEffect( () => {
    const abortController = new AbortController();

    async function fetchData() {
      console.log('Calling fetch...')
      try {
        const response = await fetch('http://localhost:4011/note', {
          signal: abortController.signal,
        });

        if (response.ok) {
          console.log('Response received from server and is ok!')
          const {note} = await response.json();

          if (abortController.signal.aborted) {
            console.log('Abort detected, exiting!')
            return;
          }

          setNote(note)
        }
      } catch(e) {
        console.log(e)
      }
    }

    fetchData()

    return () => {
      console.log('Aborting GET request.')
      abortController.abort();
    }
  }, [])

  return (
    <div>
      <RenderData
        data={note}
      />
      <Form
        entity={note}
        onSubmitHandler={async newNote => {
          const response = await fetch('http://localhost:4011/note', {
            method: 'POST',
            body: JSON.stringify(newNote),
            headers: {
              'Content-Type': 'application/json'
            }
          });

          if (response.ok) {
            const res = await response.json()
            console.log(res)
          }
        }}
      />
    </div>
  );
};

export default AddEditNote


이 코드를 실행하고 양식으로 이동하여 값을 편집한 다음 제출을 클릭하고 서버 콘솔을 살펴보면 양식에 입력한 값이 서버에 다시 게시되고 HTTP 메시지에서 추출된 것을 볼 수 있습니다.

다음으로 데이터베이스를 추가합니다...

코드 저장소: Github Repository

좋은 웹페이지 즐겨찾기