91일차 - JPA, React (React, Spring 서버 연결)

Yohan·2024년 7월 3일
0

코딩기록

목록 보기
133/156
post-custom-banner

리액트 파일 생성시 크기별로 생성

  • 사이즈에 따라 layout > pages > components
  • layout에는 제일 큰 것, 그 안에 pageg, 그 안에 가장 작은 것들은 components

React, Spring 서버 연결

  • 서버에서 데이터 GET으로 가져오기
import React, { useState, useEffect } from 'react'
import { Link } from 'react-router-dom';



const Events = () => {

    const [eventList, setEventList] = useState([]);

    // 무한루프를 막기위해 최초1번만 실행되도록 useEffect 사용
    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();

                            // loader가 리턴한 데이터는 loader를 선언한 컴포넌트와 그 하위 컴포넌트에서
                            // 언제든 불러서 사용할 수 있다.
                            
                            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;

// loader를 app.js로부터 아웃소싱
export const loader = async () => {

    const response = await fetch('http://localhost:8282/events');

    // const jsonData = await response.json();

    // loader에서 fetch의 결과를 바로 리턴하면
    // 알아서 json을 추출해서 위의 코드를 생략할 수 있다.

    return response;
}
  • app.js
import React from 'react';

...

import Events, {loader} from './components/RouteExample/pages/Events';

...


// 라우터 설정
const router = createBrowserRouter([
    {

      ...
      
                children: [
                    {
                        index: true,
                        element: <Events />,
                        loader: loader, // ← import해온 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;
}
  • ErrorPage.js
import React from 'react';
import MainNavigation from '../layout/MainNavigation';
import { useRouteError } from 'react-router-dom'
import EventNavigation from '../layout/EventNavigation'


const ErrorPage = () => {
    
    // 에러가 발생했을 때 throw에 전달한 객체를 읽는 방법
    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;
profile
백엔드 개발자
post-custom-banner

0개의 댓글