본문 바로가기
부트캠프 개발일지 2023-2024/React 리액트

[9주차] 리액트심화: 비동기 통신 axios(post, delete,patch) 하기

by whereanna00 2023. 11. 28.

이전 포스트의 프로젝트 코드에 이어서 합니다.

axios (get)

 

[9주차] 리액트심화: 비동기 통신 axios(get) 하기

지난 번 스탠다드 반에서 배운 axios, fetch를 통한 비동기 통신 내용은 아래 글을 확인하면 된다. [7주차] 스탠다드 특강 : 리액트 라이프사이클, axios, loading/error 리액트 라이프사이클 리액트 라이

whereannalee.tistory.com


axios (post) 하기

보통 서버에 데이터를 추가할 때 사용한다.

** post 요청에 대한 로직은 백엔드 개발자가 구현하는 것이기 때문에, 데이터 추가 이외의 다른용도로도 사용될 수 있지만, 보통은 클라이언트의 데이터를 body 형태로 서버에 보내고자 할 때 사용한다

axios.post(url[, data[, config]])   // POST

 

 

input 필드를 만들어, 그곳에 사용자가 데이터를 적어 제출하면 데이터를 추가하는 방식으로 코드 구현을 하며 axios post 감 잡기

1. UI 만들기

1-1. input, button 태그 추가

  return (
    <div>
      {/* input 영역 */}
      <div>
        <form>
          <input type="text" />
          <button>추가</button>
        </form>
      </div>
      {/* 데이터 영역 */}
      <div>
        {todos?.map((item)=> {
          return(
            <div key={item.id}>
              {item.id} : {item.title}
            </div>
          );
        })}
      </div>
    </div>
  );

 

 

1-2. input에 입력되는 value에 대한 state 생성 및,  onChange 추가

  const [inputValue, setInputValue] = useState({
    title: '',
  });

 

서버 데이터가 json 형식으로 되어 있기 때문에, {} 객체형태로 넣어준다. id값은 보통 json 형식 문서에서 자동으로 생성되기에 제외하고 title값만 초기값으로 빈문자열을 넣어준다.

 

          <input value={inputValue} onChange={(e)=>{
            setInputValue({ title: e.target.value,});
          }} type="text" />

 

 

1-3. 추가버튼에 onClick 넣어주기

  const [todos, setTodos] = useState(null);
  const [inputValue, setInputValue] = useState({
    title: '',
  });
  const fetchTodos = async() => {
    const {data} = await axios.get('http://localhost:3001/todos');
    console.log('response', data);
    setTodos(data);
  }

  const onSubmitHandler = async() => {
    await axios.post('http://localhost:3001/todos', inputValue);
    // 컴포넌트에도 랜더링되게 하기 (state 도 바꾸기)
    setTodos([...todos, inputValue ]);
  }

  useEffect (() => {
    //db로부터 값을 가져오기
    fetchTodos();
  }, [])

  return (
    <div>
      {/* input 영역 */}
      <div>
        <form onSubmit={(e)=>{
          e.preventDefault();
          // 버튼 클릭 시, input에 들어있는 값(state)를 이용하여 DB에 저장(post 요청)
          onSubmitHandler();
          setInputValue("");
        }}>
          <input value={inputValue.title} onChange={(ev)=>{
            setInputValue({ title: ev.target.value});
          }} type="text" />
          <button type="submit">추가</button>
        </form>
      </div>
      {/* 데이터 영역 */}
      <div>
        {todos?.map((item)=> {
          return(
            <div key={item.id}>
              {item.id} : {item.title}
            </div>
          );
        })}
      </div>
    </div>
  );

 

 

전체코드

더보기
import axios from "axios";
import { useEffect, useState } from "react";

function App() {
  const [todos, setTodos] = useState(null);
  const [inputValue, setInputValue] = useState({
    title: '',
  });
  const fetchTodos = async() => {
    await const {data} = await axios.get('http://localhost:3001/todos');
    console.log('response', data);
    setTodos(data);
  }

  const onSubmitHandler = async() => {
    axios.post('http://localhost:3001/todos', inputValue);
    // 컴포넌트에도 랜더링되게 하기 (state 도 바꾸기)
    setTodos([...todos, inputValue ]);
  }

  useEffect (() => {
    //db로부터 값을 가져오기
    fetchTodos();
  }, [])


  return (
    <div>
      {/* input 영역 */}
      <div>
        <form onSubmit={(e)=>{
          e.preventDefault();
          // 버튼 클릭 시, input에 들어있는 값(state)를 이용하여 DB에 저장(post 요청)
          onSubmitHandler();
          setInputValue("");
        }}>
          <input value={inputValue.title} onChange={(ev)=>{
            setInputValue({ title: ev.target.value});
          }} type="text" />
          <button type="submit">추가</button>
        </form>
      </div>
      {/* 데이터 영역 */}
      <div>
        {todos?.map((item)=> {
          return(
            <div key={item.id}>
              {item.id} : {item.title}
            </div>
          );
        })}
      </div>
    </div>
  );
}

export default App;

 

 


axios (delete) 하기

저장되어 있는 데이터를 삭제하고자 요청을 보낼 때 사용한다.

axios.delete(url[, config])  // DELETE

 

 

1. 삭제 UI 만들기

 

        {todos?.map((item)=> {
          return(
            <div key={item.id}>
              {item.id} : {item.title} &nbsp; <button>삭제</button>
            </div>
          );
        })}

 

 

2. onClick

  const onDeleteHandler = async(id) => {
    await axios.delete(`http://localhost:3001/todos/${id}`);
    setTodos(todos.filter((item)=> item.id !== id));
  }
        {todos?.map((item)=> {
          return(
            <div key={item.id}>
              {item.id} : {item.title} &nbsp; <button onClick={()=> onDeleteHandler(item.id)}>삭제</button>
            </div>
          );
        })}

 

 

전체코드

더보기
import axios from "axios";
import { useEffect, useState } from "react";

function App() {
  const [todos, setTodos] = useState(null);
  const [inputValue, setInputValue] = useState({
    title: '',
  });
  const fetchTodos = async() => {
    const {data} = await axios.get('http://localhost:3001/todos');
    console.log('response', data);
    setTodos(data);
  }

  const onSubmitHandler = async() => {
    await axios.post('http://localhost:3001/todos', inputValue);
    // 컴포넌트에도 랜더링되게 하기 (state 도 바꾸기)
    setTodos([...todos, inputValue ]);
  }

  const onDeleteHandler = async(id) => {
    await axios.delete(`http://localhost:3001/todos/${id}`);
    setTodos(todos.filter((item)=> item.id !== id));
  }

  useEffect (() => {
    //db로부터 값을 가져오기
    fetchTodos();
  }, [])


  return (
    <div>
      {/* input 영역 */}
      <div>
        <form onSubmit={(e)=>{
          e.preventDefault();
          // 버튼 클릭 시, input에 들어있는 값(state)를 이용하여 DB에 저장(post 요청)
          onSubmitHandler();
          setInputValue("");
        }}>
          <input value={inputValue.title} onChange={(ev)=>{
            setInputValue({ title: ev.target.value});
          }} type="text" />
          <button type="submit">추가</button>
        </form>
      </div>
      {/* 데이터 영역 */}
      <div>
        {todos?.map((item)=> {
          return(
            <div key={item.id}>
              {item.id} : {item.title} &nbsp; <button onClick={()=> onDeleteHandler(item.id)}>삭제</button>
            </div>
          );
        })}
      </div>
    </div>
  );
}

export default App;

 


axios (patch) 하기

어떤 데이터를 수정하고자 서버에 요청을 보낼 때 사용하는 메서드이다.

**이것은 http 환경에서 서로가 한 약속이자 문맥이기때문에, 수정을 하고자 반드시 patch, put 을 써야만 하는 것은 아니다. 백엔드팀에 의해서 POST를 통해서 “수정" 이라는 기능은 충분히 만들 수 있기 때문. 다만 이러한 약속들을 대부분의 개발자들이 지키고 있다.

axios.patch(url[, data[, config]])  // PATCH

 

 

1. UI 그리기

1-1. 수정할 수 있는 아이디 input 과 내용 input 창을 추가한다. (수정할 데이터의 아이디를 적고, 내용을 수정하는 식으로)

      <form>
        <input type="text" placeholder="수정할 아이디"/>
        <input type="text" placeholder="수정할 내용"/>
        <button>수정</button>
      </form>
더보기
  return (
    <div>
      {/* 수정 영역 */}
      <form>
        <input type="text" placeholder="수정할 아이디"/>
        <input type="text" placeholder="수정할 내용"/>
        <button>수정</button>
      </form>
      {/* input 영역 */}
      <div>
        <form onSubmit={(e)=>{
          e.preventDefault();
          // 버튼 클릭 시, input에 들어있는 값(state)를 이용하여 DB에 저장(post 요청)
          onSubmitHandler();
          setInputValue("");
        }}>
          <input value={inputValue.title} onChange={(ev)=>{
            setInputValue({ title: ev.target.value});
          }} type="text" />
          <button type="submit">추가</button>
        </form>
      </div>
      {/* 데이터 영역 */}
      <div>
        {todos?.map((item)=> {
          return(
            <div key={item.id}>
              {item.id} : {item.title} &nbsp; <button onClick={()=> onDeleteHandler(item.id)}>삭제</button>
            </div>
          );
        })}
      </div>
    </div>
  );

 

1-2. 수정되는 아이디와 내용에 대한 state 만들기

  const [editedId, setEditedId] = useState('');
  const [editedContent, setEditedContent] = useState('');

 

 

1-3. onChange, onSubmit(버튼 클릭시 이벤트) 만들기

      <form>
        <input value={editedId} type="text" placeholder="수정할 아이디" onChange={(e) => {
          setEditedId(e.target.value);
        }}/>
        <input value={editedContent} type="text" placeholder="수정할 내용" onChange={(e)=> {
          setEditedContent(e.target.value);
        }}/>
        <button onClick={()=> onUpdatedHandler(editedId, editedContent)}>수정반영하기</button>
      </form>
  // 수정함수
  const onUpdatedHandler = async() => {
    await axios.patch(`http://localhost:3001/todos/${editedId}`,{
      title: editedContent,
    })
    setTodos(todos.map((item)=>{
      if(item.id == editedId){
        return {...item, title: editedContent}
      } else {
        return item;
      }
      })
    );
  }

 

전체코드

더보기
import axios from "axios";
import { useEffect, useState } from "react";

function App() {
  const [todos, setTodos] = useState(null);
  const [inputValue, setInputValue] = useState({
    title: '',
  });
  const [editedId, setEditedId] = useState('');
  const [editedContent, setEditedContent] = useState('');

  // 조회 함수
  const fetchTodos = async() => {
    const {data} = await axios.get('http://localhost:3001/todos');
    console.log('response', data);
    setTodos(data);
  }

  // 추가 함수
  const onSubmitHandler = async() => {
    await axios.post('http://localhost:3001/todos', inputValue);
    // 컴포넌트에도 랜더링되게 하기 (state 도 바꾸기)
    setTodos([...todos, inputValue ]);
  }


  // 삭제 함수
  const onDeleteHandler = async(id) => {
    await axios.delete(`http://localhost:3001/todos/${id}`);
    setTodos(todos.filter((item)=> item.id !== id));
  }

  useEffect (() => {
    //db로부터 값을 가져오기
    fetchTodos();
  }, [])

  // 수정함수
  const onUpdatedHandler = async() => {
    await axios.patch(`http://localhost:3001/todos/${editedId}`,{
      title: editedContent,
    })
    setTodos(todos.map((item)=>{
      if(item.id == editedId){
        return {...item, title: editedContent}
      } else {
        return item;
      }
      })
    );
  }

  return (
    <div>
      {/* 수정 영역 */}
      <form>
        <input value={editedId} type="text" placeholder="수정할 아이디" onChange={(e) => {
          setEditedId(e.target.value);
        }}/>
        <input value={editedContent} type="text" placeholder="수정할 내용" onChange={(e)=> {
          setEditedContent(e.target.value);
        }}/>
        <button onClick={()=> onUpdatedHandler(editedId, editedContent)}>수정반영하기</button>
      </form>
      {/* input 영역 */}
      <div>
        <form onSubmit={(e)=>{
          e.preventDefault();
          // 버튼 클릭 시, input에 들어있는 값(state)를 이용하여 DB에 저장(post 요청)
          onSubmitHandler();
          setInputValue("");
        }}>
          <input value={inputValue.title} onChange={(ev)=>{
            setInputValue({ title: ev.target.value});
          }} type="text" />
          <button type="submit">추가</button>
        </form>
      </div>
      {/* 데이터 영역 */}
      <div>
        {todos?.map((item)=> {
          return(
            <div key={item.id}>
              {item.id} : {item.title} &nbsp; <button onClick={()=> onDeleteHandler(item.id)}>삭제</button>
            </div>
          );
        })}
      </div>
    </div>
  );
}

export default App;

 


+ 에러 해결하기

추가 버튼을 눌렀을 때, 에러가 뜨면서 id가 입력이 안된채로 업데이트가 된다.

 

이게 왜 생기나?

DB에는 id가 자동으로 입력되지만, state에서는 id 값을 알 수 없기 때문이다.

 

이런 경우에는, 아래 코드에서 setTodos(~) 를 사용하는 것 보단 아예 DB에서 데이터를 가져오는 게 낫다.

  // 추가 함수
  const onSubmitHandler = async() => {
    await axios.post('http://localhost:3001/todos', inputValue);
    // 컴포넌트에도 랜더링되게 하기 (state 도 바꾸기)
    setTodos([...todos, inputValue ]);
  }

 

변경후,

  // 추가 함수
  const onSubmitHandler = async() => {
    await axios.post('http://localhost:3001/todos', inputValue);
    // 컴포넌트에도 랜더링되게 하기 (state 도 바꾸기)
    // setTodos([...todos, inputValue ]);
    fetchTodos();
  }

 

 


참고

 

GitHub - dancinncoder/axios-GPDP

Contribute to dancinncoder/axios-GPDP development by creating an account on GitHub.

github.com

 

728x90
반응형