2차 공부/TIL

24.07.11 json server와 axios를 이용하여 데이터 통신하기

공대탈출 2024. 7. 11. 17:34

1. 라이브러리 설치

yarn add json-server	//json server 추가
yarn add axios	//axios 추가

 

2. 공식문서를 통해 사용법 확인하기

 

시작하기 | Axios Docs

시작하기 브라우저와 node.js에서 사용할 수 있는 Promise 기반 HTTP 클라이언트 라이브러리 Axios란? Axios는 node.js와 브라우저를 위한 Promise 기반 HTTP 클라이언트 입니다. 그것은 동형 입니다(동일한 코

axios-http.com

 

 

json-server

[![Node.js CI](https://github.com/typicode/json-server/actions/workflows/node.js.yml/badge.svg)](https://github.com/typicode/json-server/actions/workflows/node.js.yml). Latest version: 1.0.0-beta.1, last published: a month ago. Start using json-server in y

www.npmjs.com

 

3. 데이터 생성

db.json 파일을 만들어 준 뒤, get요청을 확인하기 위한 원하는 모양의 데이터를 넣어준다.

 

4. json server 실행

json server은 사용자의 컴퓨터에서 실행하는 서버이므로 개인이 실행해주어야 한다.

yarn json-server --watch db.json --port 3001	//3001번 포트로 json server 실행

정상실행 시 위와 같은 메시지가 터미널에 표시된다.

 

5. json server 확인

해당 포트번호의 데이터 항목으로 들어가 정상적인 임시데이터가 출력되는지 확인한다.

 

6. get요청 테스트

// src/App.js

import React, { useEffect, useState } from "react";
import axios from "axios";

const App = () => {
    const [todos, setTodos] = useState(null);
    const fetchTodos = async () => {
        const { data } = await axios.get("http://localhost:3001/todos");
        setTodos(data);
    };

    useEffect(() => {
        fetchTodos();
    }, []);
    console.log(todos);
    
    return <div>App</div>;
};

export default App;

Todo를 저장할 todos state를 만들어주고, 서버에 get요청을 보낸다. 이때 요청 명령어는 공식문서에서 확인가능하다.

get요청을 하고 setTodo하여 state에 저장하는데, 이 함수를 useEffect를 사용하여 컴포넌트가 마운트 되었을 때 한번만 실행하도록 설정한다.

따라서 컴포넌트가 마운트 되면 콘솔에 todo가 찍히게 된다.

 

7. Post 요청 테스트

// src/App.js

import React, { useEffect, useState } from 'react';
import axios from 'axios';

const App = () => {
    const [todos, setTodos] = useState(null);
    const [todo, setTodo] = useState({ title: '' });
    const fetchTodos = async () => {
        const { data } = await axios.get('http://localhost:3001/todos');
        setTodos(data);
    };
    const onSubmitHandler = (todo) => {
        axios.post('http://localhost:3001/todos', todo);
    };

    useEffect(() => {
        fetchTodos();
    }, []);

    console.log(todos); // App.js:16
    return (
        <>
            {' '}
            <form
                onSubmit={(e) => {
                    // 👇 submit했을 때 브라우저의 새로고침을 방지합니다.
                    e.preventDefault();
                    onSubmitHandler(todo);
                }}
            >
                {' '}
                <input
                    type="text"
                    onChange={(ev) => {
                        const { value } = ev.target;
                        setTodo({ ...todo, title: value });
                    }}
                />{' '}
                <button>추가하기</button>{' '}
            </form>{' '}
            <div>
                {' '}
                {todos?.map((todo) => (
                    <div key={todo.id}>
                        {todo.title}
                    </div>
                ))}{' '}
            </div>{' '}
        </>
    );
};

export default App;

똑같이 위와같이 공식문서에서 POST의 명령문 작성법을 확인하고 작성한다. input에 입력한 값을 todo state에 저장하고 해당 값을 post요청에 담아 보낸다.

요청을 보낸 뒤 새로고침을 하면 데이터가 추가되어 밑의 todos.map에 의해 화면에 뿌려진다.

하지만 새로고침을 하면 리액트의 장점을 얻을 수 없으므로, post한 뒤 todos state에 추가하여 리렌더링을 유발시켜 사용자에게 새롭게 뿌려준다.

// src/App.js

import React, { useEffect, useState } from 'react';
import axios from 'axios';

const App = () => {
    const [todos, setTodos] = useState(null);
    const [todo, setTodo] = useState({ title: '' });
    const fetchTodos = async () => {
        const { data } = await axios.get('http://localhost:3001/todos');
        setTodos(data);
    };
    const onSubmitHandler = (todo) => {
        axios.post('http://localhost:3001/todos', todo);
    //------todos에 추가하여 리렌더링-----
    //------todos에 추가하여 리렌더링-----
        setTodos([...todos, todo]);
    //------todos에 추가하여 리렌더링-----
    //------todos에 추가하여 리렌더링-----
    };

    useEffect(() => {
        fetchTodos();
    }, []);

    console.log(todos); // App.js:16
    return (
        <>
            {' '}
            <form
                onSubmit={(e) => {
                    // 👇 submit했을 때 브라우저의 새로고침을 방지합니다.
                    e.preventDefault();
                    onSubmitHandler(todo);
                }}
            >
                {' '}
                <input
                    type="text"
                    onChange={(ev) => {
                        const { value } = ev.target;
                        setTodo({ ...todo, title: value });
                    }}
                />{' '}
                <button>추가하기</button>{' '}
            </form>{' '}
            <div>
                {' '}
                {todos?.map((todo) => (
                    <div key={todo.id}>
                        {todo.title}
                    </div>
                ))}{' '}
            </div>{' '}
        </>
    );
};

export default App;

 

 

8. DELETE 테스트

// src/App.js

import React, { useEffect, useState } from 'react';
import axios from 'axios';

const App = () => {
    const [todos, setTodos] = useState(null);
    const [todo, setTodo] = useState({ title: '' });
    const fetchTodos = async () => {
        const { data } = await axios.get('http://localhost:3001/todos');
        setTodos(data);
    };
    const onSubmitHandler = (todo) => {
        axios.post('http://localhost:3001/todos', todo);
        setTodos([...todos, todo]);
    };
    const onClickDelteButtonHandler = (todoId) => {
        axios.delete(`http://localhost:3001/todos/${todoId}`);
        let newTodos = todos.filter((el) => el.id !== todoId);
        setTodos([...newTodos]);
    };

    useEffect(() => {
        fetchTodos();
    }, []);
    
    return (
        <>
            {' '}
            <form
                onSubmit={(e) => {
                    // 👇 submit했을 때 브라우저의 새로고침을 방지합니다.
                    e.preventDefault();
                    onSubmitHandler(todo);
                }}
            >
                {' '}
                <input
                    type="text"
                    onChange={(ev) => {
                        const { value } = ev.target;
                        setTodo({ ...todo, title: value });
                    }}
                />{' '}
                <button>추가하기</button>{' '}
            </form>{' '}
            <div>
                {' '}
                {todos?.map((todo) => (
                    <div key={todo.id}>
                        {todo.title}
                        <button
                            type="button"
                            onClick={() => {
                                onClickDelteButtonHandler(todo.id);
                            }}
                        >
                            삭제
                        </button>
                    </div>
                ))}{' '}
            </div>{' '}
        </>
    );
};

export default App;

각 todo에 삭제버튼을 추가하여 onClickDeleteButtonHandler함수를 추가해주었다.

해당 함수는 todo의 id값을 인자로 받아 서버에 해당 id값을 Delete하는 명령을 보내고, 기존 todos state에서 같은 id값을 가지고 있는 것을 제거하여 사용자에게 즉각리렌더링을 경험하게 한다.

 

9. PATCH 테스트

// src/App.jsx

import React, { useEffect, useState } from 'react';
import axios from 'axios';

const App = () => {
    const [todo, setTodo] = useState({
        title: '',
    });
    const [todos, setTodos] = useState(null);

    // patch에서 사용할 id, 수정값의 state를 추가
    const [targetId, setTargetId] = useState(null);
    const [editTodo, setEditTodo] = useState({
        title: '',
    });

    const fetchTodos = async () => {
        const { data } = await axios.get('http://localhost:3001/todos');
        setTodos(data);
    };

    const onSubmitHandler = (todo) => {
        axios.post('http://localhost:3001/todos', todo);
    };

    const onClickDeleteButtonHandler = (todoId) => {
        axios.delete(`http://localhost:3001/todos/${todoId}`);
    };

    // 수정버튼 이벤트 핸들러 추가 👇
    const onClickEditButtonHandler = (todoId, edit) => {
        axios.patch(`http://localhost:3001/todos/${todoId}`, edit);
    };

    useEffect(() => {
        fetchTodos();
    }, []);

    return (
        <>
            <form
                onSubmit={(e) => {
                    e.preventDefault();
                    onSubmitHandler(todo);
                }}
            >
                {/* 👇 수정기능에 필요한 id, 수정값 input2개와 수정하기 버튼을 추가 */}
                <div>
                    <input
                        type="text"
                        placeholder="수정하고싶은 Todo ID"
                        onChange={(ev) => {
                            setTargetId(ev.target.value);
                        }}
                    />
                    <input
                        type="text"
                        placeholder="수정값 입력"
                        onChange={(ev) => {
                            setEditTodo({
                                ...editTodo,
                                title: ev.target.value,
                            });
                        }}
                    />
                    <button
                        // type='button' 을 추가해야 form의 영향에서 벗어남
                        type="button"
                        onClick={() => onClickEditButtonHandler(targetId, editTodo)}
                    >
                        수정하기
                    </button>
                </div>
                <input
                    type="text"
                    onChange={(ev) => {
                        const { value } = ev.target;
                        setTodo({
                            ...todo,
                            title: value,
                        });
                    }}
                />
                <button>추가하기</button>
            </form>
            <div>
                {todos?.map((todo) => (
                    <div key={todo.id}>
                        {/* todo의 아이디를 화면에 표시 */}
                        {todo.id} :{todo.title}
                        <button type="button" onClick={() => onClickDeleteButtonHandler(todo.id)}>
                            삭제하기
                        </button>
                    </div>
                ))}
            </div>
        </>
    );
};

export default App;

수정할 값을 입력할 input을 만들고 수정하기 위해 todo의 id값을 사용자에게 보여주는 형식이다

사용자는 id값과 수정할 내용을 input에 작성하고 수정버튼을 누르면 해당 id를 가진 todo가 수정된다.