티스토리 뷰

<Outlet>

상위 경로와 일치하는 하위 경로를 렌더링한다.

import { Outlet } from "@remix-run/react";

export default function SomeParent() {
  return (
    <div>
      <h1>Parent Content</h1>
      <Outlet />
    </div>
  );
}

 

 

Props

context

outlet 아래의 엘리먼트 트리에 컨텍스트 값을 전달한다. 상위 경로가 하위 경로에 값을 제공해야 할 때 사용한다.

<Outlet context={myContextValue} />

 

하위 컴포넌트에서 전달받은 컨텍스트를 가져올 때는 useOutletContext를 사용한다.

 

 

 


<Await>

useLoaderData에서 액세스한 지연된 로더 promise를 해결하는 역할을 한다.

import { Await } from "@remix-run/react";

<Suspense fallback={<div>Loading...</div>}>
  <Await resolve={somePromise}>
    {(resolvedValue) => <p>{resolvedValue}</p>}
  </Await>
</Suspense>;

 

 

Props

resolve

데이터가 스트리밍되는 시점을 해결하기 위해 useLoaderData에서 promise를 가져온다.

<Await resolve={somePromise} />

 

promise가 완료되지 않으면, 상위 suspense 바운더리의 대체가 렌더링된다.

<Suspense fallback={<div>Loading...</div>}>
  <Await resolve={somePromise} />
</Suspense>

promise가 완료되면, children이 렌더링된다.

 

 

children

children은 콜백 또는 React 엘리먼트가 렌더링될 수 있다.

<Await resolve={somePromise}>
  {(resolvedValue) => <p>{resolvedValue}</p>}
</Await>

 

children props가 React 엘리먼트라면, 성공 값은 하위 트리에 useAsyncValue를 통해 접근할 수 있다.

<Await resolve={somePromise}>
  <SomeChild />
</Await>

// 하위 트리
import { useAsyncValue } from "@remix-run/react";

function SomeChild() {
  const value = useAsyncValue();
  return <p>{value}</p>;
}

 

 

errorElement

promise가 실패할 때, 에러 바운더리를 렌더할 수 있다.

<Await errorElement={<div>Oops!</div>} />

 

에러는 하위 트리에서 useAsyncError를 통해 접근할 수 있다.

<Await errorElement={<SomeChild />} />


// 하위 컴포넌트
import { useAsyncError } from "@remix-run/react";

function SomeChild() {
  const error = useAsyncError();
  return <p>{error.message}</p>;
}

 

 

 

 

 


<Form>

fetch를 통해 action에 데이터를 제출하고 기본 HTML 폼 이상의 향상된 유저 인터페이스를 활성화하는 useNavigation에서 보류 상태를 활성화하는 점진적으로 향상된 HTML <form>이다.

폼의 action이 완료되면, 페이지의 모든 데이터가 서버에서 자동으로 재검증되어 UI와 데이터의 동기화가 유지된다.

 

HTML 폼 API를 사용하기 때문에, 서버에서 렌더링된 페이지는 JavaScript가 로드되기 전에 기본 수준에서 상호작용한다.

Remix가 제출물을 관리하는 대신, 브라우저는 제출물은 물론 보류 상태(회전하는 파비콘 등)도 관리한다. JavaScript가 로드된 후 Remix가 웹 애플리케이션 사용자 경험을 활성화한다.

 

Formdms URL도 변경해야 하거나 브라우저 기록 스택에 항목을 추가해야 하는 제출에 가장 유용하다.

브라우저 기록 스택을 조작해서는 안되는 폼의 경우 <fetcher.Form>을 사용하세요.

import { Form } from "@remix-run/react";

function NewEvent() {
  return (
    <Form action="/events" method="post">
      <input name="title" type="text" />
      <input name="description" type="text" />
    </Form>
  );
}

 

 

Props

action

폼 데이터를 제출할 URL

undefined일 경우, 컨텍스트에서 가장 가까운 경로가 기본값이다.

상위 경로가 <Form>을 렌더링하지만 URL이 더 깊은 하위 경로와 일치하는 경우 폼은 상위 경로에 게시된다.

마찬가지로 하위 경로 내부의 내부의 폼은 하위 경로에 게시된다. 이는 항상 전체 URL을 가리키는 기존의 <form>과는 다르다.

 

 

method

사용할 HTTP 동사를 결정한다.

DELETE, GET, PATCH, POST, PUT. 기본값은 GET

<Form method="post" />

기본 <form>은 GET 및 POST 만 지원하므로 점진적인 향상을 지원하려면 다른 동사를 피해야한다.

 

 

encType

폼 제출에 사용할 인코딩 유형

<Form encType="multipart/form-data" />

기본값은 application/x-www-form-urlencoded. 파일 업로드에는 multipart/form-data를 사용한다.

 

 

navigate

<Form navigate={false} >를 지정하여 탐색을 건너뛰고 내부적으로 fetcher를 사용하도록 폼에 지시할 수 있다.

이는 본질적으로 결과 데이터에 신경쓰지 않고 제출을 시작하고 useFetchers( )를 통해 보류 상태에 액세스하려는 useFetcher( ) + <fetcher.Form>의 약어이다.

<Form method="post" navigate={false} />

 

 

fetcherKey

비탐색 Form을 사용할 때, 선택적으로 사용할 자체 fetcher key를 지정할 수 있다.

<Form method="post" navigate={false} fetcherKey="my-key" />

 

 

preventScrollReset

<ScrollRestoration> 을 사용하는 경우, 폼을 제출할 때 스크롤 위치가 창 상단으로 재설정되는 것을 방지할 수 있다.

<Form preventScrollReset />

 

 

replace

새 항목을 푸시하는 대신 기록 스택의 현재 항목을 바꾼다.

<Form replace />

 

 

reloadDocument

true인 경우 클라이언트 측 라우팅 대신 브라우저를 사용하여 폼을 제출한다.

기존의 <form>과 동일하다.

<Form reloadDocument />

<form>이상으로 권장된다. action prop이 생략되면, <Form>과 <form>은 현재 URL이 무엇인지에 따라 다른 action을 호출하는 경우가 있다. <form>은 현재 URL을 기본값으로 사용하지만, <Form>은 폼이 렌더링되는 라우트의 URL을 사용하기 때문이다.

 

 

unstable_viewTransition

document.startViewTransition( )에서 최종 상태 업데이트를 래핑하여 탐색에 대한 View Transition을 활성화한다.

뷰 전환에 특정 스타일을 적용해야 하는 경우 unstable_useViewTransitionState( )도 활용해야 한다.

 

 

 

✏️ NOTE

?index

index 경로와 해당 상위 경로는 동일한 URL을 공유하므로 이를 구별하는 데 ?index 매개변수가 사용된다.

<Form action="/accounts?index" method="post" />

 

action URL route action
/accounts?index app/routes/accounts._index.tsx
/accounts app/routes/accounts.tsx

 

 

 

 


<Link>

클라이언트 측 라우팅으로 탐색을 활성화하는 <a href> 랩퍼이다.

import { Link } from "@remix-run/react";

<Link to="/dashboard">Dashboard</Link>;

 

 

Props

to: string

가장 기본적인 사용법

<Link to="/some/path" />

 

 

to: Partial<Path>

Partial<Path> 값을 전달할 수도 있다.

<Link
  to={{
    pathname: "/some/path",
    search: "?query=string",
    hash: "#hash",
  }}
/>

 

 

prefetch

링크에 대한 데이터 및 모듈 프리패치 동작을 정의한다.

<>
  <Link /> {/* defaults to "none" */}
  <Link prefetch="none" />
  <Link prefetch="intent" />
  <Link prefetch="render" />
  <Link prefetch="viewport" />
</>
  • none - 기본값. 프리패칭 없음
  • intent - 유저가 링크에 마우스를 올리거나 포커스를 두면 프리패치
  • render - 링크가 렌더링될 때 프리패치
  • viewport - 링크가 뷰포트에 있을 때 프리패치. 모바일에 매우 유용함

프리패칭은 HTML <link rel="prefetch"> 태그를 사용해 수행된다. 태그들은 link 뒤에 삽입된다.

<nav>
  <a href="..." />
  <a href="..." />
  <link rel="prefetch" /> {/* might conditionally render */}
</nav>

때문에 nav: last-child를 사용한다면, 스타일이 조건부로 마지막 링크(및 기타 유사한 셀렉터)에서 떨어지지 않도록 nav: last-of-type을 사용해야 한다.

 

 

preventScrollReset

<ScrollRestoration>을 사용하는 경우 링크를 클릭할 때 스크롤 위치가 창 상단으로 재설정되는 것을 방지할 수 있다.

<Link to="?tab=one" preventScrollReset />

유저가 뒤로/앞으로 버튼이 있는 위치로 돌아올 때 스크롤 위치가 복원되는 것을 방지하지 않으며, 유저가 링크를 클릭할 때 재설정되는 것을 방지할 뿐이다.

 

 

relative

링크의 상대 경로 동작을 정의한다.

<Link to=".." />; // default: "route"
<Link relative="route" />;
<Link relative="path" />;
  • route - 기본값. 경로 계층 구조에 상대적이므로 ".."는 현재 경로 패턴의 모든 URL 세그먼트를 제거함
  • path - 경로에 상대적이므로 ".."는 하나의 URL 세그먼트를 제거함

 

 

reloadDocument

링크를 클릭할 때 클라이언트 측 라우팅 대신 문서 탐색을 사용하고, 브라우저는 전환을 정상적으로 처리한다.(마치 <a href>가 있던 것처럼)

<Link to="/logout" reloadDocument />

 

 

replace

새 항목을 푸시하는 대신 기록 스택의 현재 항목을 대체한다.

<Link replace />

# 기록스택이 다음과 같다면
A -> B

# 보통의 링크 클릭은 새 항목을 추가함
A -> B -> C

# 하지만 replace는 B가 C로 대체됨
A -> C

 

 

state

영구적인 클라이언트 측 라우팅 상태를 그 다음 위치에 추가한다.

<Link to="/somewhere/else" state={{ some: "value" }} />

 

위치 상태는 location에서 액세스된다.

function SomeComp() {
  const location = useLocation();
  location.state; // { some: "value" }
}

이 상태는 history.state 위에 구현되므로 서버에서 접근할 수 없다.

 

 

unstable_viewTransition

document.startViewTransition( )에서 최종 상태 업데이트를 래핑하여 탐색에 대한 View Transition을 활성화한다.

<Link to={to} unstable_viewTransition>
  Click me
</Link>

 

View Transition에 특정 스타일을 적용해야 하는 경우 unstable_useViewTransitionState( )도 활용해야 한다.

function ImageLink(to) {
  const isTransitioning =
    unstable_useViewTransitionState(to);
  return (
    <Link to={to} unstable_viewTransition>
      <p
        style={{
          viewTransitionName: isTransitioning
            ? "image-title"
            : "",
        }}
      >
        Image Number {idx}
      </p>
      <img
        src={src}
        alt={`Img ${idx}`}
        style={{
          viewTransitionName: isTransitioning
            ? "image-expand"
            : "",
        }}
      />
    </Link>
  );
}

 

 

 

 


<Links />

라우트 모듈 링크 내보내기로 생성된 모든 <link> 태그를 렌더링한다.

일반적으로 app/root.tsx에 있는 HTML의 <head> 내부에 렌더링해야 한다.

// app/root.tsx
import { Links } from "@remix-run/react";

export default function Root() {
  return (
    <html>
      <head>
        <Links />
      </head>
      <body></body>
    </html>
  );
}

 

 

 

 

 


<NavLink>

active 및 pending 상태 스타일을 지정하기 위한 추가 props로 <Link>를 감싼다.

import { NavLink } from "@remix-run/react";

<NavLink
  to="/messages"
  className={({ isActive, isPending }) =>
    isPending ? "pending" : isActive ? "active" : ""
  }
>
  Messages
</NavLink>;

 

 

자동 속성

.active

active 클래스가 활성화되면 <NavLink>에 추가되므로 CSS를 사용해 스타일링을 할 수 있다.

<NavLink to="/messages" />


a.active {
  color: red;
}

 

 

aria-current

NavLink가 활성화되면 기본 앵커 태그에 <a aria-current="page"> 가 자동으로 적용된다.

 

 

.pending

pending 클래스가 탐색 중에 보류 중이라면 <NavLink>에 추가되므로 CSS를 사용해 스타일링할 수 있다.

<NavLink to="/messages" />


a.pending {
  color: red;
}

 

 

.transitioning

탐색 중에 <NavLink unstable_viewTransition>컴포넌트가 전환될 때 transitioning 클래스가 컴포넌트에 추가되므로 CSS를 사용해 스타일링할 수 있다.

<NavLink to="/messages" unstable_viewTransition />


a.transitioning {
  view-transition-name: my-transition;
}

 

 

 

 

Props

className 콜백

적용된 클래스 이름을 사용자화할 수 있도록 active 및 pending 상태로 콜백

<NavLink
  to="/messages"
  className={({ isActive, isPending }) =>
    isPending ? "pending" : isActive ? "active" : ""
  }
>
  Messages
</NavLink>

 

 

style 콜백

적용된 스타일을 사용자화할 수 있도록 active 및 pending 상태로 콜백

<NavLink
  to="/messages"
  style={({ isActive, isPending }) => {
    return {
      fontWeight: isActive ? "bold" : "",
      color: isPending ? "red" : "black",
    };
  }}
>
  Messages
</NavLink>

 

 

children 콜백

<NavLink>의 콘텐츠를 사용자화할 수 있도록 active 및 pending 상태로 콜백

<NavLink to="/tasks">
  {({ isActive, isPending }) => (
    <span className={isActive ? "active" : ""}>Tasks</span>
  )}
</NavLink>

 

 

end

NavLink의 to 경로에만 일치하도록 active와 pending 상태에 대한 일치 논리를 변경한다.

to보다 URL이 더 긴 경우에는 더 이상 active로 간주되지 않는다.

 

Link URL isActive
<NavLink to="/tasks" /> /tasks true
<NavLink to="/tasks /> /tasks/123 true
<NavLink to="/tasks" end /> /tasks true
<NavLink to="/tasks" end /> /tasks/123 false <- URL이 to 경로보다 김

 

모든 URL이 /와 일치하기 때문에 <NavLink to="/" >는 예외적인 경우이다.

기본적으로 모든 단일 경로와 일치하는 것을 피하기 위해 end prop을 효과적으로 무시하고 루트 경로에 있을 때만 일치한다.

 

 

caseSensitive

caseSensitive를 추가하면 일치 논리가 대소문자를 구분하도록 변경한다.

Link URL isActive
<NavLink to="/SpOnGe-b0B" /> /sponge-bob true
<NavLink to="/SpOnGe-boB" caseSeneitive /> /sponge-bob false

 

 

unstable_viewTransition

document.startViewTransition( )에서의 최종 상태 업데이트를 래핑하여 탐색에 대한 View Transition을 활성화한다.

기본적으로 전환 중에, 보기 전환을 사용자화하는 데 사용할 수 있는 transitioning 클래스가 <a> 엘리먼트에 추가된다.

a.transitioning p {
  view-transition-name: "image-title";
}

a.transitioning img {
  view-transition-name: "image-expand";
}


<NavLink to={to} unstable_viewTransition>
  <p>Image Number {idx}</p>
  <img src={src} alt={`Img ${idx}`} />
</NavLink>

 

isTransitioning 값에 따라 추가로 사용자화하기 위해 className/style props 또는 children에 전달된 렌더링 props를 사용할 수도 있다.

 

<NavLink to={to} unstable_viewTransition>
  {({ isTransitioning }) => (
    <>
      <p
        style={{
          viewTransitionName: isTransitioning
            ? "image-title"
            : "",
        }}
      >
        Image Number {idx}
      </p>
      <img
        src={src}
        alt={`Img ${idx}`}
        style={{
          viewTransitionName: isTransitioning
            ? "image-expand"
            : "",
        }}
      />
    </>
  )}
</NavLink>

 

 

 


<PrefetchPageLinks />

페이지의 모든 assets를 프리패치하여 해당 페이지를 즉시 탐색할 수 있다.

이는 특정 페이지의 모든 assets(데이터, 모듈, CSS)에 대해 <link rel="prefetch"> 및 <link rel="modulepreload" /> 태그를 렌더링하여 수행한다.

 

<Link rel="prefetch">는 이를 내부적으로 사용하지만 다른 이유로 페이지를 프리페치하도록 렌더링할 수 있다.

<PrefetchPageLinks page="/absolute/path/to/your-path" />

 

단, 절대 경로를 사용해야 한다.

 

 

 


<LiveReload />

앱을 Remix asset 서버에 연결하고 개발 중에 파일이 변경되면 자동으로 페이지를 다시 로드한다.

프로덕션에서는 null을 렌더링하므로 항상 루트 경로에서 안전하게 렌더링할 수 있다.

// app/root.tsx
import { LiveReload } from "@remix-run/react";

export default function Root() {
  return (
    <html>
      <head />
      <body>
        <LiveReload />
      </body>
    </html>
  );
}

 

 

Props

origin

Live Reload 프로토콜의 사용자 정의 원본을 지정한다.

제공된 URL은 http 프로토콜을 사용해야 하며 내부적으로 ws 프로토콜로 업그레이드 된다. 이는 Remix 개발 서버 앞에서 역방향 프록시를 사용할 때 유용하다.

기본값은 REMIX_DEV_ORIGIN 환경 변수이거나 REMIX_DEV_ORIGIN이 설정되지 않은 경우에만 window.location.origin이다.

 

 

port

Live Reload 프로토콜에 대한 사용자 정의 포트를 지정한다.

기본값은 REMIX_DEV_ORIGIN 환경 변수에서 파생된 포트이거나 REMIX_DEV_ORIGIN이 설정되지 않은 경우에만 8002이다.

 

 

timeoutMs

Live Reload 프로토콜에 대한 사용자 지정 시간 초과를 밀리초 단위로 지정할 수 있다.

웹 소켓 연결이 끊어진 경우 다시 연결을 시도하기 전의 지연 시간이다.

기본값은 1000이다.

 

 

 


<Meta />

라우트 모듈 meta 내보내기에 의해 생성된 모든 <meta> 태그를 렌더링한다.

일반적으로 app/root.tsx에 있는 HTML의 <head> 내부에 렌더링해야 한다.

// app/root.tsx
import { Meta } from "@remix-run/react";

export default function Root() {
  return (
    <html>
      <head>
        <Meta />
      </head>
      <body></body>
    </html>
  );
}

 

 

 

 


<Scripts />

앱의 클라이언트 런타임을 렌더링한다.

일반적으로 app/root.tsx에 있는 HTML의 <body> 내부에서 렌더링해야 한다.

// app/root.tsx
import { Scripts } from "@remix-run/react";

export default function Root() {
  return (
    <html>
      <head />
      <body>
        <Scripts />
      </body>
    </html>
  );
}

<Scripts /> 컴포넌트를 렌더링하지 않는다면, 앱은 HTML 및 브라우저 동작에만 의존하여 JavaScript 없이 기존 웹 앱처럼 계속 동작한다.

 

 

Props

<Scripts> 컴포넌트는 특정 속성을 통해 기본 <script>태그로 전달할 수 있다.

  • <Scripts crossOrigin > - 앱과 다른 서버에서 정적 assets를 호스팅하기 위함
  • <Scripts nonce > - <script>태그에 대한 nonce-sources가 있는 스크립트에 대한 콘텐츠 보안 정책을 지원
async / defer / src / type / noModule 등의 속성은 Remix 내부에서 관리되기 때문에 전달할 수 없다.

 

 

 


<ScrollRestoration>

loader가 완료된 후 위치 변경 시 브라우저의 스크롤 복원을 에뮬레이트한다.

이렇게 하면 여러 도메인에서도 스크롤 위치가 적시에 올바른 지점으로 복원된다.

 

<Scripts /> 컴포넌트 바로 앞에 이들 중 하나만 렌더링해야 한다.

import {
  Scripts,
  ScrollRestoration,
} from "@remix-run/react";

export default function Root() {
  return (
    <html>
      <body>
        {/* ... */}
        <ScrollRestoration />
        <Scripts />
      </body>
    </html>
  );
}

 

 

Props

getKey

선택 항목. 스크롤 위치를 복원하는 데 사용되는 키를 정의한다.

<ScrollRestoration
  getKey={(location, matches) => {
    // default behavior
    return location.key;
  }}
/>

 

 

nonce

<ScrollRestoration>은 스크롤 깜빡임을 방지하기 위해 인라인 <script>를 렌더링한다.

nonce prop은 CSP nonce 사용을 허용하기 위해 script 태그로 전달된다.

<ScrollRestoration nonce={cspNonce} />

 

 

 

Preventing Scroll Reset

새 위치로 이동하면 스크롤 위치가 페이지 상단으로 재설정된다.

링크와 폼에서 "맨 위로 스크롤" 동작을 방지할 수 있다.

<Link preventScrollReset={true} />;
<Form preventScrollReset={true} />;
728x90