실험한 깃 레포
https://github.com/JeonInguk/Parallel-Routes-Next-app-router
GitHub - JeonInguk/Parallel-Routes-Next-app-router
Contribute to JeonInguk/Parallel-Routes-Next-app-router development by creating an account on GitHub.
github.com
Parallel Routes
Parallel Routes의 존재이유는 각 경로가 독립적으로 스트리밍될 때 각 경로에 대해 독립적인 오류 및 로딩 상태를 정의할 수 있다는 점이다.
export default function Layout(props: {
children: React.ReactNode
analytics: React.ReactNode
team: React.ReactNode
}) {
return (
<>
{props.children}
{props.team}
{props.analytics}
</>
)
}
Parallel Routes을 사용하면 인증 상태와 같은 특정 조건에 따라 조건부로 슬롯을 렌더링할 수도 있다. 이를 통해 동일한 URL에서 완전히 분리된 코드를 사용할 수 있다.
Convention
- 슬롯은 경로 segment 아니며 URL 구조에 영향을 미치지 않는다. 파일 경로 /@team/members는 /members에서 액세스할 수 있음
- app/page.js의 URI은 app/@children/page.js의 구조로 접속하는 것과 같다.
Unmatched Routes
- 기본적으로 슬롯 내에서 렌더링되는 콘텐츠는 현재 URL과 일치한다.
-> (app/page.js의 URI은 app/@children/page.js의 구조로 접속하는 것과 같다는 뜻) - 일치하지 않는 슬롯의 경우 라우팅 기술 및 폴더 구조에 따라 Next.js가 렌더링하는 콘텐츠가 달라진다.
-> 몽말인지 모르겠음;;(ㅇ?ㅇ)
default.js
Next.js가 현재 URL을 기반으로 슬롯의 활성 상태를 복구할 수 없을 때 대체 파일로 렌더링할 default.js 파일을 정의할 수 있다.
다음 폴더 구조를 고려해보자. 팀 슬롯에는 설정 디렉터리가 있지만 @analytics에는 설정 디렉터리가 없다.
-> reset()으로 오류 복구하려할때 안되면 defalut.js가 나타난다는 말인듯..?
useSelectedLayoutSegment(s)
'use client'
import { useSelectedLayoutSegment } from 'next/navigation'
export default async function Layout(props: {
//...
auth: React.ReactNode
}) {
const loginSegments = useSelectedLayoutSegment('auth')
// ...
}
사용자가 URL 표시줄에서 @auth/login 또는 /login으로 이동하면 로그인 세그먼트는 "login" 문자열과 동일하다.
실험
글로만 봐서 이해갈듯말듯 하지만 적용하려고 보면 적용안된다. 직접 실험해보자.
폴더구조
error.tsx
"use client"; // 에러 컴포넌트는 항상 Client Component여야 합니다.
import { useEffect } from "react";
export default function Error({ error, reset }: { error: Error; reset: () => void }) {
useEffect(() => {
console.error(error);
}, [error]);
return (
<>
<h2>Left 컴포넌트에서 에러 발생했음!</h2>
<button onClick={() => reset()}>다시 시도하기</button>
</>
);
}
loading.tsx
import React from "react";
export default function Loading() {
return <>왼쪽 로딩중...</>;
}
page.tsx
export default async function Left() {
await new Promise((resolve) => setTimeout(resolve, 2 * 1000));
// throw new Error("주석을 풀어서 일부로 에러를 발생시켜보세요🤙");
const value = Math.random();
return (
<>
<div className="w-40 mr-20 bg-orange-400 h-80">왼쪽 {value}</div>
</>
);
}
global-error.tsx
"use client"; // 에러 컴포넌트는 항상 Client Component여야 합니다.
import { useEffect } from "react";
export default function Error({ error, reset }: { error: Error; reset: () => void }) {
useEffect(() => {
console.error(error);
}, [error]);
return (
// global-error는 html태그와 body 꼭 추가시켜주셔야합니다잉
<html>
<body>
<div>
<h2>전역 어디선가 에러가 발생했음!</h2>
<button onClick={() => reset()}>다시 시도하기</button>
</div>
</body>
</html>
);
}
layout.tsx
import "./globals.css";
import { ErrorBoundary } from "react-error-boundary";
import Error from "./global-error";
export default function RootLayout(props: { children: React.ReactNode; Left: React.ReactNode; Right: React.ReactNode }) {
return (
<html lang="en">
<body>
<ErrorBoundary fallback={<Error />}>
<div className="flex flex-row items-center justify-center w-screen h-20 text-3xl bg-amber-400">네비게이션바인척 하는놈</div>
<div className="flex flex-row justify-center mt-20 flex-nowrap">
{props.children}
{props.Left}
{props.Right}
</div>
</ErrorBoundary>
</body>
</html>
);
}
(루트)page.tsx
import Another from "@/Components/Another";
export default function Home() {
return (
<>
<Another />
</>
);
}
실험결과 의도한대로 잘 작동된다.
각 페이지별 로딩상태 다름
각 페이지별 에러상태 다름(여기서는 Left만 에러발생시켜서 Left만 에러가 발생했습니다잉)
'Next.js(ver.13) > Routing' 카테고리의 다른 글
Intercepting Routes (0) | 2023.08.04 |
---|---|
Error Handling (0) | 2023.08.02 |
Loading UI and Streaming (0) | 2023.08.02 |
Route Groups (0) | 2023.08.01 |
Linking and Navigating (0) | 2023.08.01 |