카테고리 없음

React Hooks 적용하기

나아눙 2023. 3. 24. 10:01

json-server 라이브러리

직접 DB를 만들고 서버를 구축할 필요 없이 json 파일을 이용하여 REST API 서버를 구축해주는 라이브러리

json-server는 앱의 프로토타입을 만들거나 학습을 위해 서버가 필요할 때 사용하는 용도

json-server --watch data.json --port 3001

이 시스템에서 스크립트를 실행 할수 없다고 에러가 나왔다.

스터디홀에서 질문하여 해결방법을 찾았다

VSCode 오류 : 이 시스템에서 스크립트를 실행할 수 없으므로 ... (tistory.com)

 

VSCode 오류 : 이 시스템에서 스크립트를 실행할 수 없으므로 ...

VSCode 오류 : 이 시스템에서 스크립트를 실행할 수 없으므로... VSCode의 터미널을 통하여 npm혹은 yarn을 사용하여 처음 작업을 수행할 때, 다음과같은 에러가 발생할 수 있습니다. 내용은 "이 시스템

hellcoding.tistory.com

 

BlogDetail.js

useParams()는 React Router v5부터 제공되는 Hook으로, URL 경로에서 동적으로 변하는 값을 가져올 수 있도록 해준다.

 

useNavigate()React Router v6에서 사용 가능한 새로운 Hook으로, hook을 호출하여 navigate 변수에 할당

튼 클릭 시 특정 페이지로 이동하고 싶을 때 navigate('/path/to/page')와 같이 navigate() 함수를 호출하여 페이지 이동을 처리

 

handleDeleteClick() 함수는 삭제 버튼을 클릭했을 때 호출되며, setTimeout() 함수를 사용하여 1초 후에 API 요청을 보낸다. 이렇게 1초 후에 요청을 보내는 이유는, 사용자가 잠시 기다리는 것을 표시하기 위해서이다.

API 요청은 fetch() 함수를 사용하여 서버의 /blogs/${id} 엔드포인트에 HTTP DELETE 메소드를 사용하여 보내며,

해당 게시물의 ID는 id 변수에서 가져옵니다. 이렇게 보낸 요청이 성공적으로 처리되면, navigate() 함수를 사용하여 루트 경로로 이동하고 window.location.reload()함수를 사용하여 페이지를 새로고침한다.

만약 요청에 오류가 있다면, catch() 함수에서 오류를 처리하고 해당 코드에서는 콘솔에 오류 메시지를 출력하도록 한다.

 const handleDeleteClick = () => {
    /* delete 버튼을 누르면 다시 home으로 리다이렉트 되어야 합니다. */
    /* useNavigate()를 이용하여 handleDeleteClick 로직을 작성해주세요. */
   
    fetch(`http://localhost:3001/blogs/${id}`,
   {method:'Delete',
    headers:{'Content-Type':'application/json'},
    })
      .then(res => {
        if (!res.ok) {
          throw Error('could not fetch the data for that resource');
        } 
        return res.json();
      })
      .then(()=>{
  
        navigate('/');
        navigate(0);
        //window.location.reload() 새로고침 자동
        
      })
      .catch(err => {

        console.error('Error');
      })
    

      
    }

 

handleLikeClick() 함수는 좋아요 버튼을 클릭하면 실행되며, setIsLike(!isLike)를 호출하여 isLike 상태 값을 토글(toggle)한다. 이렇게 하는 이유는, 좋아요 버튼이 눌려있는지 여부를 상태 값으로 유지하기 위해서다.

게시물의 좋아요 수를 증가시키기 위해 PATCH 메소드를 사용하여 /blogs/${id} 엔드포인트로 API 요청을 보낸다.

이때, 좋아요 수를 증가시키기 위한 데이터는 let patchDtata = {'likes' : blog.likes +1 }와 같이 구성되며,

JSON 형식으로 바꾸어서 요청의 body에 담겨 보낸다.

const handleLikeClick = () => {
    /* 하트를 누르면 home에서 새로고침을 했을 때 숫자가 올라가야 합니다. */
    /* isLike와 blog.likes를 이용하여 handleLikeClick의 로직을 작성해주세요. */
    setIsLike(!isLike);
    const data = {
      "likes":blog.likes+1 }
    fetch(`http://localhost:3001/blogs/${id}`,
   {method:'PATCH',
    headers:{'Content-Type':'application/json'},
    body:JSON.stringify(data)})
      .then(res => {
        if (!res.ok) {
          throw Error('could not fetch the data for that resource');
        } 
        return res.json();
      })
      .catch(err => {

        console.error('Error');
      })
    console.log('like!');
  }

 

{ isPending && <Loading/> }은 isPending 값이 참(true)일 경우, 즉 API 요청이 아직 처리 중일 때 Loading 컴포넌트를 렌더링한다.

{ error && <div>{ error }</div> }는 API 요청이 실패하거나 오류가 발생했을 때, error 값이 존재할 경우 해당 오류 메시지를 출력한다.

{ blog && (...) }는 blog 값이 존재하는 경우, 즉 API 요청이 성공적으로 처리되어 게시물 정보가 제공되었을 때, 해당 게시물의 세부 정보를 표시한다.

 

CreateBlog.js

handleSubmit 함수는 제출 이벤트를 처리하며, 입력된 데이터를 바탕으로 새로운 블로그를 생성한다.

데이터는 JSON.stringify()를 사용하여 문자열로 변환한 후 POST 메소드를 사용하여 서버로 전송된다.

서버 응답이 성공하면 navigate() 메소드를 사용하여 브라우저 URL을 업데이트하고, 페이지를 다시 로드한다.

import { useState } from "react";
import { useNavigate } from "react-router-dom";

const CreateBlog = () => {
    const [title, setTitle] = useState('');
    const [body, setBody] = useState('');
    const [author, setAuthor] = useState('김코딩');
    const navigate = useNavigate();

    const handleSubmit = (e) => {
        e.preventDefault();
        /* 등록 버튼을 누르면 게시물이 등록이 되며 home으로 리다이렉트 되어야 합니다. */
        /* 작성한 내용과 useNavigate를 이용하여 handleSubmit의 로직을 작성해보세요. */
        let data = {
        "title": title,
        "body": body,
        "author": author,
        "likes": 0
      };

        fetch('http://localhost:3001/blogs/',
        {method:'POST',
         headers:{'Content-Type':'application/json'},
         body:JSON.stringify(data)})
           .then(res => {
             if (!res.ok) {
               throw Error('could not fetch the data for that resource');
             } 
             return res.json();
           }).then(()=>{
            navigate('/');
           })
           .catch(err => {
            return err.message;
           })

       console.log(e.type);
    }

 

UseFetch.js

React Hook인 useFetch를 정의하는 함수이다.

이 Hook은 URL을 매개변수로 받아서 해당 URL에서 데이터를 가져오고 이 데이터, 로딩 상태 및 오류를 관리한다.

useFetch Hook은 useEffect를 사용하여 데이터를 가져오는데, 1초 후에 URL에서 데이터를 가져온다.

데이터가 가져와지면 해당 데이터, 로딩 상태 및 오류 상태를 관리하는 상태 변수를 업데이트한다.

마지막으로, useFetch Hook은 데이터, 로딩 상태 및 오류를 포함하는 배열을 반환한다.

이 배열은 컴포넌트에서 분해하여 사용할 수 있다.

import { useState, useEffect } from 'react';

const useFetch = (url) => {
  /* useState를 이용하여 data, isPending, error를 정의하세요. */
  /* useFetch 안의 중심 로직을 작성해주세요. */
  const [blogs, setBlogs] = useState(null);
  const [isPending, setIsPending] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    setTimeout(() => {
      fetch(url)
      .then(res => {
        if (!res.ok) {
          throw Error('could not fetch the data for that resource');
        } 
        return res.json();
      })
      .then(data => {
        setIsPending(false);
        setBlogs(data);
        setError(null);
      })
      .catch(err => {
        setIsPending(false);
        setError(err.message);
      })
    }, 1000);
  }, [])

  return [blogs,isPending,error]
}

 
export default useFetch;

App.js

 const [blogs,isPending,error] =useFetch('http://localhost:3001/blogs')

 

BlogDetail.js

const [blog,isPending,error] =useFetch(`http://localhost:3001/blogs/${id}`)

if(!res.ok){

 thorow new Error(res.statusText);

}

.catch(error) =>{

  setError(err.message);

}

//catch는 어떤 에러가 나오는지 알수 있다.