
리액트 훅이라고하면 일반적으로 use- 접미사로 시작을 한다.
그런데 use 만 덩그러니인 것이 나타났다!?
이건 리액트 훅일까 아닐까? 🧐
| Promise 나 Context 와 같은 데이터를 참조하는 React API 이다.
// 형태
const value = use(resource)
resource
Promise 또는 Context 일 수 있다.Promise 일 경우, 항상 같은 Promise 인스턴스를 전달해야한다.Promise 를 생성하게되면, 무한반복에 빠질 수 있다. ☠️// 무한반복에 빠지는 경우
import { Suspense } from 'react'
import { ErrorBoundary } from 'react-error-boundary'
import { Users, Spinner, ErrorFallback } from '@/components'
import { fetchUsers } from '@/api'
export default function App() {
// ❌ 렌더링마다 새로운 Promise 생성
const promise = fetchUsers()
return (
<ErrorBoundary FallbackComponent={ErrorFallback}>
<Suspense fallback={<Spinner />}>
<Users promise={promise} />
</Suspense>
</ErrorBoundary>
)
}
// 무한반복에 빠지지 않는 경우
import { Suspense, useMemo } from 'react'
import { ErrorBoundary } from 'react-error-boundary'
import { Users, Spinner, ErrorFallback } from '@/components'
import { fetchUsers } from '@/api'
export default function App() {
// ✅ 의존성 배열이 빈 배열이므로 최초 한 번만 생성됨
const promise = useMemo(() => fetchUsers(), [])
return (
<ErrorBoundary FallbackComponent={ErrorFallback}>
<Suspense fallback={<Spinner />}>
<Users promise={promise} />
</Suspense>
</ErrorBoundary>
)
}
💡 참고사항
Next.js 서버 컴포넌트는 렌더링이 한 번만 이루어지므로use함수로Promise를 직접 사용해도 무한반복이 일어나지 않는다.export default function ServerComponent() { // 서버 컴포넌트는 한 번만 렌더링되므로 // use 함수에서 직접 Promise를 사용해도 안전합니다. const data = use(fetchUsers()) return (...) }
Promise 또는 Context 에서 참조한 값을 반환한다.
useState, useEffect)과는 달리 조건문, 반복문 내에서도 사용이 가능하다.useContext 처럼 작동할 수 있다.useContext 와의 차이점은 조건문내에서 사용할 수 있다는 점이다.)서버 컴포넌트 에서 데이터를 가져올 때는 use 를 사용하기보다는 async 및 await 를 사용하는 것이 좋다. async 및 await는 await 이 호출된 시점부터 렌더링을 시작하지만, use 는 데이터가 리졸브된 이후부터 컴포넌트를 렌더링하기 때문이다.클라이언트 컴포넌트 에서 Promise 를 생성하는 것보다 서버 컴포넌트 에서 생성하여 클라이언트 컴포너느로 전달하는 것이 좋다. 서버 컴포넌트에서는 렌더링이 한 번만 이루어지는 반면 클라이언트 컴포넌트에서는 렌더링할 때마다 Promise가 재생성되기 때문이다.use로 Promise를 호출했을 때 Promise 의 상태에 따라 Suspense 와 Error Boundary 는 다음과같이 작동한다.
pending → Suspense 의 fallback 를 보여준다.fulfilled → resolve 된 값을 반환하여 화면에 렌더링한다.rejected → Error Boundary 로 에러를 전달한다.✋🏻 잠깐! 그렇다면 Suspense 와 Error Boundary가 없다면 use 로 Promise 를 호출할 수 없는걸까?
호출은 할 수 있지만, pending 상태일 때와 rejected상태일 때의 렌더링처리를 어떻게 해야할지 모르는 상태가 되기때문에 렌더링 멈춤현상이 발생하거나 에러가 발생할 수 있다.
⇒ 안전하게 동작하기 위해서는 Suspense 와 Error Boundary로 감싸주자!
use는 함수의 형태를 가진 훅의 규칙을 따르고 훅처럼 동작하는 API이다. (1인 2역)