리액트 파일 생성시 크기별로 생성
- 사이즈에 따라
layout > pages > components
- layout에는 제일 큰 것, 그 안에 pageg, 그 안에 가장 작은 것들은 components
React, Spring 서버 연결
import React, { useState, useEffect } from 'react'
import { Link } from 'react-router-dom';
const Events = () => {
const [eventList, setEventList] = useState([]);
useEffect(() => {
const fetchEvents = async () => {
const response = await fetch('http://localhost:8282/events');
const jsonData = await response.json();
setEventList(jsonData)
};
fetchEvents();
}, []);
return (
<>
<h1>Events Page</h1>
<ul>
{eventList.map((event) => (
<li key={event.id}>
<Link to={event.id}>{event.title}</Link>
</li>
))}
</ul>
</>
)
}
export default Events
loader
- useEffect 대신에 loader를 통해서 fetch가능 (요즘 버전)
import React from 'react';
...
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
const router = createBrowserRouter([
{
path: '/',
element: <RootLayout />,
errorElement: <ErrorPage />,
children: [
{ index: true, element: <Home /> },
{
path: 'events',
element: <EventLayout />,
children: [
{
index: true,
element: <Events />,
loader: async () => {
const response = await fetch('http://localhost:8282/events');
const jsonData = await response.json();
return jsonData;
}
},
{ path: ':eventId', element: <EventDetail /> },
{ path: 'new', element: <NewEvent />},
]
},
]
},
]);
const App = () => {
return (
<RouterProvider router={router} />
);
};
export default App;
loader 아웃소싱
- router가 커지고, 여러 함수들이 생겨나면 지저분해진다.
그래서 사용하는 컴포넌트에서 loader함수를 정의하고 export해도 괜찮다.
- Events.js
import React from 'react';
const Events = () => {
const eventList = useLoaderData();
return (
<>
<h1>Events Page</h1>
<EventList eventList={eventList} />
</>
);
};
export default Events;
export const loader = async () => {
const response = await fetch('http://localhost:8282/events');
return response;
}
import React from 'react';
...
import Events, {loader} from './components/RouteExample/pages/Events';
...
const router = createBrowserRouter([
{
...
children: [
{
index: true,
element: <Events />,
loader: loader,
},
{ path: ':eventId', element: <EventDetail /> },
{ path: 'new', element: <NewEvent />},
]
},
...
};
export default App;
Error 예외처리하기
- fetch의 결과가 200이 아닐때의 예외처리하기
- loader함수에서 예외상황시 메세지와, 상태번호를 객체에 담아서 throw new Response.
- 그럼 라우터에 의해 미리 만들어 놓은 ErrorPage로 이동하게 된다.
errorElement: <ErrorPage />
- loader 함수
export default Events;
// loader를 app.js로부터 아웃소싱
export const loader = async () => {
const response = await fetch('http://localhost:8282/events');
if (response.status !== 200) {
const errorText = await response.text();
throw new Response(
JSON.stringify({ message: errorText }),
{
status: response.status,
}
); // ErrorPage로 연결.
}
return response;
}
import React from 'react';
import MainNavigation from '../layout/MainNavigation';
import { useRouteError } from 'react-router-dom'
import EventNavigation from '../layout/EventNavigation'
const ErrorPage = () => {
const error = useRouteError();
let errorMessage;
if (error.status === 400) {
errorMessage = JSON.parse(error.data).message;
}
if (error.status === 404) {
errorMessage = '페이지를 찾을 수 없습니다. URL을 확인하세요!~'
}
return (
<>
<MainNavigation />
<EventNavigation />
<main>
<h1>에러가 발생했습니다!</h1>
<p>{errorMessage}</p>
</main>
</>
);
};
export default ErrorPage;