[React : mini-project] CRUD(3) - Read Detail

문지은·2023년 7월 30일
0

React

목록 보기
18/24
post-thumbnail
post-custom-banner

Read Detail

DetailPage 라우트 추가

  • pages 디렉토리에 DetailPage.jsx 생성하고 라우트 추가하기
  • post의 id를 URL 파라미터로 지정

src/routes.js

import HomePage from './pages/HomePage';
import CreatePage from './pages/CreatePage';
import EditPage from './pages/EditPage';
import ListPage from './pages/ListPage';

// *************** DetailPage import
import DetailPage from './pages/DetailPage';


const routes = [
  {
    path:'/',
    element: <HomePage />
  },
  {
    path:'/blogs',
    element: <ListPage />
  },
  {
    path:'/blogs/create',
    element: <CreatePage />
  },
  {
    path:'/blogs/edit',
    element: <EditPage />
  },
  // ******************** Detail 페이지 라우트 추가
  {
    path:'/blogs/:id',
    element: <DetailPage />
  },
]

export default routes;

Detail 페이지 작성

  • react router의 useParams Hook을 사용하여 URL로부터 post의 id를 받아오고 axios get 요청을 하여 post 정보 받아오기 (getPost)
  • 이전에 만든 LoadingSpinner 컴포넌트를 사용하여 로딩중일 경우에는 LoadingSpinner 출력하도록 작성
  • getPost를 한번만 실행하도록 useEffect 사용하고 id가 변경될 때마다 함수 실행하도록 의존성 배열을 [id]로 설정

src/pages/DetailPage.jsx

import React, { useEffect, useState } from 'react'
import { useParams } from 'react-router-dom'
import axios from 'axios'
import LoadingSpinner from '../components/LoadingSpinner'

function DetailPage() {
  const { id } = useParams();
  const [post, setPost] = useState(null);
  const [loading, setLoading] = useState(true);

  const getPost = (id) => {
    axios.get(`http://localhost:3001/posts/${id}`)
    .then((res) => {
        setPost(res.data)
        setLoading(false)
    })
  }

  useEffect(() => {
    getPost(id)
  }, [id])  // id가 변경될 때마다 함수 실행

  if (loading) {
    return <LoadingSpinner />
  }
  return (
    <div>
        <h1>{post.title}</h1>
        <p>{post.body}</p>
    </div>
  )
}

export default DetailPage
  • /blogs/:id 로 접근시 DetailPage로 이동 확인

Detail Page 링크 추가

  • 카드를 클릭하면 해당 Post의 DetailPage로 이동하도록 코드 수정

src/pages/ListPage.jsx

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

function ListPage() {
  ...
	const navigate = useNavigate();
  
    if (posts.length === 0) {
      return (<div>'No blog posts found'</div>)
    }

    return posts.map(post => {
      return (
        // ************** 카드 클릭시 DetailPage로 이동
        <Card 
          key={post.id} 
          title={post.title} 
          onClick={() => navigate(`/blogs/${post.id}`)}>
          <button 
            className="btn btn-danger btn-sm" 
            onClick={(event) => deleteBlog(event, post.id)}>
            Delete</button>
        </Card>
      )
    })
  }
...
export default ListPage

Post 생성 시간 추가하기

  • Post를 Create 할 때 생성시간도 함께 저장하도록 BlogForm 수정

src/components/BlogForm.jsx

...

function BlogForm() {
  ...

  const onSubmit = () => {
      axios.post('http://localhost:3001/posts', {
      title: title,
      body: body,
      // ************** 생성 시간 추가
      createdAt: Date.now()
      }).then(() => {
        navigate('/blogs')
      })
  }
  ...

export default BlogForm
  • 새로운 게시글 작성 후 생성 시간 함께 저장되는 것 확인
  • 생성시간이 저장되어 있지 않은 데이터들은 삭제하고 계속 진행
  • 게시글 DetailPage에 생성 시간 출력하도록 수정

src/pages/DetailPage.jsx

...

function DetailPage() {
  ...
  
  if (loading) {
    return <LoadingSpinner />
  }
  return (
    <div>
        <h1>{post.title}</h1>
      // ************** 생성 시간 추가
        <small class="text-muted">{post.createdAt}</small>
        <p>{post.body}</p>
    </div>
  )
}

export default DetailPage
  • 생성시간 함께 출력되지만 우리가 알아볼 수 없는 형태임
  • 우리가 알아볼 수 있는 형태로 출력하도록 코드 수정
...

function DetailPage() {
  ...
  
  // ****** 날짜 출력 형태 바꾸어주는 함수 ********
  const printDate = (timestamp) => {
    return new Date(timestamp).toLocaleString();
  }

  if (loading) {
    return <LoadingSpinner />
  }
  return (
    <div>
        <h1>{post.title}</h1>
      // ********** 수정 **********
        <small class="text-muted">작성 시간 : {printDate(post.createdAt)}</small>
        <p>{post.body}</p>
    </div>
  )
}

export default DetailPage
  • 출력 확인
profile
코드로 꿈을 펼치는 개발자의 이야기, 노력과 열정이 가득한 곳 🌈
post-custom-banner

1개의 댓글

comment-user-thumbnail
2023년 7월 30일

이런 유용한 정보를 나눠주셔서 감사합니다.

답글 달기