[React] loader

정호·2024년 4월 4일
0

TIL

목록 보기
14/15

loader

함수를 값으로 취하는 프로퍼티 이 페이지를 라우팅하기전에 이 함수를 실행해줌
-> loader안에 데이터를 로딩하고 가져올 수 있음

이전 fetch코드 Event.js

function EventsPage() {
  const [isLoading, setIsLoading] = useState(false);
  const [fetchedEvents, setFetchedEvents] = useState();
  const [error, setError] = useState();

  useEffect(() => {
    async function fetchEvents() {
      setIsLoading(true);
      const response = await fetch("http://localhost:8080/events");

      if (!response.ok) {
        setError("Fetching events failed.");
      } else {
        const resData = await response.json();
        setFetchedEvents(resData.events);
      }
      setIsLoading(false);
    }

    fetchEvents();
  }, []);

App.js 에서 라우팅할때 loader 이용

const router = createBrowserRouter([
  {
    path: "/",
    element: <RootLayout />,
    children: [
      { index: true, element: <HomePage /> },
      {
        path: "events",
        element: <EventsRootLayout />,
        children: [
          {
            index: true,
            element: <EventsPage />,
            loader: eventsLoader,
          },
          { path: ":eventId", element: <EventDetailPage /> },
          { path: "new", element: <NewEventPage /> },
          { path: ":eventId/edit", element: <EditEventPage /> },
        ],
      },
    ],
  },
]);
  • resData.events를 리턴하는이유 : 응답 데이터 객체가 실제 이벤트 어레이를 담고잇는 이벤트 프로퍼티를 갖게 되니까

Event.js
useloaderData로 events에 데이터를 삽입


function EventsPage() {
  const events = useLoaderData();

  return <EventsList events={events} />;
}

export default EventsPage;

export async function loader() {
  const response = await fetch("http://localhost:8080/events");

  if (!response.ok) {
    // ...
  } else {
    const resData = await response.json();
    return resData.events;
  }
}

❖ 로딩하려는 위치보다 더 높은 위치에서 데이터를 로딩하면 안됨


loader를 사용하면 페이지의 초기 렌더링이 완료된 후에 데이터를 가져오는 것이 아니라, 페이지가 로드되는 동안에 데이터를 가져온다.
따라서 UI적으로 로딩을 보여주는게 좋음

usenavigation

usenavigation state에 loading을 넣어줘 쉽게 처리할 수 있다.

import { Outlet, useNavigation } from "react-router-dom";

import MainNavigation from "../components/MainNavigation";

function RootLayout() {
  const navigation = useNavigation();
  return (
    <>
      <MainNavigation />
      <main>
        {navigation.state === "loading" && <p>,,,,loading</p>}
        <Outlet />
      </main>
    </>
  );
}

export default RootLayout;

loader의 사용

  • 로컬스토리지 액세스
  • 브라우저 API
  • 쿠키
  • js코드 어떤것이든 가능

usestate같은 리액트 훅은 불가능


useRouterError

function ErrorPage() {
  const error = useRouteError();

  let title = "An error occurred!";
  let message = "Something went wrong!";

  if (error.status === 500) {
    message = error.data.message;
  }

  if (error.status === 404) {
    title = "Not found!";
    message = "Could not find resource or page.";
  }

  return (
    <>
      <MainNavigation />
      <PageContent title={title}>
        <p>{message}</p>
      </PageContent>
    </>
  );
}

export default ErrorPage;
Event.js

  if (!response.ok) {
    // return { isError: true, message: 'Could not fetch events.' };
    throw new Response(JSON.stringify({ message: "Could not fetch events." }), {
      status: 500,
    });
  } else {
    return response;
  }
}

.data: HTTP 응답 오류에서는 오류와 관련된 추가적인 정보를 담고 있는 객체
.message: 오류 객체의 메시지를 나타내는 속성입
error.data.message는 오류 객체의 데이터에서 메시지를 가져오는 것

profile
열심히 기록할 예정🙃

0개의 댓글