notes
use ??
JavaScript nullish coalescing 연산자 ??의 동작·사용 기준과 주의점 메모.
한 줄로
use(리소스)= Promise 결과나 Context 값을 컴포넌트 안에서 바로 읽는 함수(조건문·반복문 안에서도 호출 가능 — 일반 훅과 다른 점)
무엇을 읽을 수 있나
1. Promise와 함께 (Suspense 연동)
async function getCamp(seq: number) {
const res = await fetch(`/api/camp/${seq}`);
return res.json();
}
function CampDetail({ campPromise }: { campPromise: Promise<Camp> }) {
const camp = use(campPromise); // resolve될 때까지 Suspense가 대기
return <h1>{camp.name}</h1>;
}
// 부모
<Suspense fallback={<Skeleton />}>
<CampDetail campPromise={getCamp(123)} />
</Suspense>
동작
- Promise가 아직 안 끝나면 → Suspense boundary로 fallback 표시
- 성공 →
use가 결과 반환 - 실패 → 가까운 Error Boundary로 전달
useEffect + useState로 fetch 하던 패턴을, 서버/부모에서 Promise 넘기고 use로 읽는 방식으로 바꿀 수 있습니다.
2. Context와 함께
const ThemeContext = createContext<'light' | 'dark'>('light');
function Button() {
const theme = use(ThemeContext); // useContext(ThemeContext)와 동일
return <button className={theme}>...</button>;
}
useContext와 비슷하지만, use는 조건문 안에서도 호출할 수 있습니다.
function Panel({ showTheme }: { showTheme: boolean }) {
if (showTheme) {
const theme = use(ThemeContext); // ✅ useContext는 여기서 불가
return <div>{theme}</div>;
}
return null;
}
일반 훅과의 차이
useEffect + fetch vs use + Promise
기존 (useEffect)
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api').then(r => r.json()).then(setData);
}, []);
if (!data) return <Loading />;
use + Suspense
const data = use(fetch('/api').then(r => r.json()));
// 로딩은 Suspense fallback이 처리
로딩 UI를 컴포넌트마다 if (!data)로 두지 않고, Suspense 한곳에서 처리할 수 있습니다.
주의할 점
- Promise는 렌더마다 새로 만들면 안 됨
매 렌더
use(fetch(...))하면 Suspense가 반복됩니다.→ 부모/
cache/useMemo등으로 안정적인 Promise를 넘기세요. - 클라이언트 컴포넌트
Next.js App Router에서는
"use client"안에서 사용합니다. - 에러 처리
reject된 Promise는 Error Boundary가 잡아야 합니다.
- 아직 모든 팀이 React 19는 아님
thankqcamping이 React 19면 사용 가능, 그 전 버전에는 없습니다.
Next.js에서 흔한 패턴
// Server Component에서 Promise 생성
export default function Page() {
const campPromise = getCampData(seq); // await 안 함
return (
<Suspense fallback={<Skeleton />}>
<CampClient campPromise={campPromise} />
</Suspense>
);
}
// Client Component
'use client';
function CampClient({ campPromise }: { campPromise: Promise<Camp> }) {
const camp = use(campPromise);
return <div>{camp.name}</div>;
}
서버에서 시작한 fetch를 클라이언트에서 use로 이어 받는 흐름입니다.
요약
use = “이 Promise/Context 값을 지금 읽어라” — 로딩은 Suspense, 실패는 Error Boundary에 맡기는 스타일입니다.