React

 

 

 

소스 :

https://github.com/braverokmc79/macaronics-react-udemy-ex24/tree/complex

 

 

App.jsx

 {
    path: "/events/:id",
    element: <EventDetails />,
    children: [
      {
        path: "/events/:id/edit",
        element: <EditEvent />,
        loader:editEventLoader,
        action:editEventAction
      },
    ],
  },

 

 

 

EditEvent.jsx

import { Link, Outlet, useNavigate, useParams } from 'react-router-dom';
import Header from '../Header.jsx';
import { useMutation, useQuery } from '@tanstack/react-query';
import { deleteEvent, fetchEvent, queryClient } from '../../util/http.js';
import LoadingIndicator from '../UI/LoadingIndicator.jsx';
import ErrorBlock from '../UI/ErrorBlock.jsx';
import { useState } from 'react';
import Modal from '../UI/Modal.jsx';

export default function EventDetails() {  
  const [isDeleting, setIsDeleting]=useState(false);


  const navigate=useNavigate();
  const {id} =useParams();

  const {data,  isPending,  isError, error }=useQuery({
    queryKey:['events', id],
    queryFn:({signal})=>fetchEvent({id, signal}),
    //캐시처리된지 10초 미만인 경우 내부적으로 다시 가져오지 않고 캐시된 데이터를 사용된다.
    staleTime:10000

  })


  const {
    mutate,  isPending:isPendingDeleting,  isError: isErrorDeleting, error: deleteError} = useMutation({
    mutationFn: deleteEvent,
    onSuccess: () => {
      queryClient.invalidateQueries({ 
          queryKey: ['events'] ,
          refetchType: 'none'
      });
      navigate('/events');
    },
  });


  
  function handleStopDelete(){
    setIsDeleting(false);
  }
  

  function handleStartDelete(){
    setIsDeleting(true);
  }
  
  function handleDeleteEvent(formData) {  
    mutate({
      id:id
  });
  }



  let content="";

  if(isPending){
    content=(
      <div id="event-details-content" className='center'>
          <p>이벤트 데이터 가져오는 중...</p>
          <LoadingIndicator />
      </div>
    )
  }

  if(isError){
    content=
    <div id="event-details-content" className='center'>      
      <ErrorBlock  title="에러가 발생 했습니다."  message={error.info?.message || '이벤트를 가져오지 못했습니다.'}  />
    </div>
  }

  if(data&& data.image){

    const formattedDate=new Date(data.date).toLocaleDateString("ko-KR", {
      day:'numeric',
      month:'short',
      year:'numeric',
      hour:'2-digit',
      minute:'2-digit',
    })

    content=<>      
         <header>
          <h1>{data.title}</h1>
          <nav>
            <button onClick={handleStartDelete}>삭제</button>
            <Link to="edit">편집</Link>
          </nav>
        </header>
        <div id="event-details-content">
          <img src={`http://localhost:3000/${data.image}`} alt={data.title} />
          <div id="event-details-info">
            <div>
              <p id="event-details-location">{ data.location}</p>
              <time dateTime={`Todo-DateT$Todo-Time`}>{formattedDate} @ {data.time}</time>
            </div>
            <p id="event-details-description">{data.description}</p>
          </div>
        </div>    
    </>
  }




  return (
    <>
      {isDeleting &&(
      <Modal onClose={handleStopDelete}>
        <h2>확인</h2>
        <p>정말로 이 이벤트를 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.</p>
        <div className='form-actions'>
          {isPendingDeleting &&<p>삭제 처리중...</p>}
          {!isPendingDeleting &&
           <>
            <button onClick={handleStopDelete} className='button-text'>취소</button>
            <button onClick={handleDeleteEvent} className='button'>삭제</button>
          </>
          }   
        </div>

          {isErrorDeleting &&<ErrorBlock  title="이벤트 삭제에 실패 하였습니다."  
                message={error.info?.message || '이벤트 삭제에 실패 하였습니다.'}  />}
      </Modal>      
    )}

      <Outlet />
      <Header>
        <Link to="/events" className="nav-item">         
          모든 이벤트 보기
        </Link>
      </Header>

      <article id="event-details" className='text-center'>
          {content}
      </article>
    </>
  );
}



 

 

 

 

 

 

 

 

 

 

 

 

about author

PHRASE

Level 60  라이트

인간은 자유다. 인간은 자유 그 자체다. -사르트르

댓글 ( 0)

댓글 남기기

작성