React Suspense의 논점
다른 한편, 우리는 이미 React18을 설치하고 사용할 수 있다.오늘 이 가운데 예전보다 더 주목받고 난산 끝에 드디어 햇빛을 본 수퍼스가 보도했다.(※ 이전부터 한정 기능이 있었다)
아직 생태계를 따르지 않은 상황에서 수spense에 대해'수spense는 이렇게 사용한다'는 논의를 진행하기에는 이르기 때문에 이 기사에서 수spense에 대해 우리가 고려해야 할 논점이 무엇인지 생각해보겠습니다.
또 수spense의 용례가 많은데 이번에는 응용 엔지니어에게 가장 친근한 수spense for Datafetching을 주로 언급했다.
개시하다
실제 동작과 기본 지식은 다른 기사에 맡기고 API를 빠르게 확인해 주세요.
<Suspense fallback={<Spinner />}>
<Comments />
</Suspense>
Comments에서suspend 상태(promise가throw 상태)에 있을 때 Comments 구성 요소가 렌더링되지 않고 Suspense의fallback을 표시합니다.기본적으로 매우 간단하다.Suspense의 참조
Suspense의 공식 문서는 여러 곳에 흩어져 있어 정보를 수집하기 어렵지만 아래 링크를 보면 이해하기 쉽다.
Suspense의 현재 사양
Suspense의 앞으로.
그럼 바로 Suspense의 논점을 살펴봅시다.
논점 1: Suspense 앞뒤 어셈블리 설계 변경 방법
Suspense를 가져오기 전에 구성 요소가 어떻게 변할까요?현재의 느낌으로 볼 때 나는'데이터가 데이터가 필요한 구성 요소에 최대한 접근해야 한다'는 방향이 더욱 강할 것이라고 생각한다.이는 colocation이라는 이름으로 유명한 React의 구성 요소 디자인의 상하문에서도 자주 언급되지만 앞으로는 Suspense에 따라 속도를 낼 것으로 보인다.
예를 들어 아래의 이런 코드는 지금 아주 잘 쓰여 있지 않습니까?요점은 ① 데이터 로드층과 ② 데이터 디스플레이층이 분리된다는 것이다.
function App() {
// ①データロード層
const [res] = useQuery({query: ListProducts})
return (
<div>
<p>商品一覧</p>
<div>
// ②データディスプレイ層
{res.fetching && <Spinner />}
{res.data?.products && res.data.products.map(p => (
<div>
<div>{p.name}</div>
<div>{p.price}</div>
</div>
))}
</div>
</div>
)
}
Suspense를 사용하면 다음과 같이 코드가 표시됩니다.function App() {
return (
<div>
<p>商品一覧</p>
<Suspense fallback={<Spinner />}>
<ProductList />
</Suspense>
</div>
)
}
function ProductList() {
// ①データロード層
const [res] = useQuery({query: ListProducts})
// ①データディスプレイ層
return (
{res.data?.products && res.data.products.map(p => (
<div>
<div>{p.name}</div>
<div>{p.price}</div>
</div>
))}
)
}
데이터 로드층과 데이터 디스플레이층이 더욱 가깝다.이때 useQuery는suspense와 대응해야 하지만 이런 상황에서 useQuery의 기술을 Suspense 밖으로 내버려 두면 당연히 움직이지 않기 때문에 colocation은 자연스럽게 달성된 코드가 된다.render-as-you-fetch와graphiql의fragment colocation에서
또한 데이터 취득층이 아니라 데이터 디스플레이층으로 쓴 것은 의도적인 것이다.조금 복잡하다면 렌더-as-you-fetch와graphiql의fragment colocation을 잘 사용하면 더 높은 층에서 얻은 처리를 정리하고 실제 파악한 순서대로 UI에 반영할 수 있다.이런 행위는 relay에서partial rendering이라고 불린다.
주변 프로그램 라이브러리 등의 대응이 필요하지만 가능하면 페이지의 맨 위에서 데이터 추출을 하고 데이터가 필요한 구성 요소에서 데이터가 표시된 훅을 사용하며 이 구성 요소는 각각 독립된Suspense로 포장합니다나는 이런 코드가 증가할 것이라고 생각한다.
지저분하게 쓰면 이런 기분이야?(특정한 라이브러리를 인상으로 쓰는 것이 아니라 허구의 라이브러리를 사용한다)
function App() {
fetchQuery({query: RootQuery}) // 省略。fragmentなり下部レイヤーのデータリクエストをまとめる
return (
<div>
<p>商品一覧</p>
<Suspense fallback={<Spinner />}>
<ProductList />
</Suspense>
<p>タグ一覧</p>
<Suspense fallback={Spinner />}>
<TagList />
</Suspense>
</div>
)
}
function ProductList() {
const [data] = useDataSource({query: ListProducts})
return (
{data && data.products.map(p => (
<div>
<div>{p.name}</div>
<div>{p.price}</div>
</div>
))}
)
}
function TagList() {
const [data] = useDataSource({query: ListTags})
return (
{data && data.tags.map(p => (
<div>
<div>{p.name}</div>
</div>
))}
)
}
코드가 병렬로 Suspense를 설정했지만 복잡한 화면과 UI 최적화 상황에서 Suspense가 중첩될 수 있습니다.마운트 상태의 UI가 글로벌 드라이어에서 로컬 드라이어로
이렇게 수spense를 이용하면 전 세계 적재구보다 국부적인 드러머를 사용한다.이전에는 까다로웠던 처리 부분인데 수spense를 가져올 때 사용자의 조작을 막지 않기 위해 글로벌한 드러머들은 대부분 피해야 할 UI로 수spense와 함께 현지 드러머를 퍼뜨리지 않았나.
논점2: 그럼 잘못된 처리는?
리액트 근처에 익숙한 분들은 이런 코드를 보셨을 거예요.
<ErrorBoundary fallback={<ErrorMessage />}>
<Suspense fallback={<Spinner />}>
<Comments />
</Suspense>
</ErrorBoundary>
Error Boundary가 Commants에서 throw에 의해 포착된 오류를 fallback에 props로 표시하는 것을 목적으로 한 코드입니다.실제로 React Core Team 중 하나인 bvaugon이 만든 프로그램 라이브러리를 사용하면 위 코드가 이동합니다.Suspense는 Promisse의 throw를 제외하고는 받지 않기 때문에 throw가 잘못된 경우 위에 있는 ErrorBoundary에 도착해서 받을 수 있다.
언뜻 보기에 이것은 매우 깨끗해 보일 것이다.하지만 이 코드의 이동을 위해서는 Comments에서 Throw Error가 필요합니다.이것은 Comments 구성 요소의 측면에서 볼 때 외부의 설치에 크게 의존한다.또한 전문가 라이브러리로서 구상한 이 실현을 감안하면 내부 실복을 의식적으로 사용할 수 없다는 것이 현실적이지 않다고 생각한다.(Suspense도 측면이 있다는 것을 부인할 수 없습니다.)
이 때문인지 최근에는 리액트의 핵심 팀이 Suspense for Datafetching 컨텍스트에서 Errorboundary를 언급하는 것을 보지 못했다.몇 가지 다른 메커니즘을 고려했을 수도 있지만 현재는 예전처럼 처리해야 한다.나는 앞으로의 동향을 주시하고 싶다.
참조:
논점 3: 생태계의 추종
react-18 작업팀에 React18에 대응하는 프로그램 라이브러리를 정리한 게시물이 있는데 참고가 될 수 있지만 아직 멀었다고 생각합니다.
Suspense와 관련해서는 최근 발표된 React 18에 대응하는 React Testing Library v13에 Suspense를 활용한 구성 요소의 테스트를 작성할 때 간단한query 패키지가 Suspense에 있는 구성 요소도 움직이지 않고 1 tick 지연시험의 cleanup이 순조롭게 돌아가지 못해 이상한 행동들만 하고 있다.
또한 Suspense는 아니지만 useSyncExternalStore의 대응 프로그램은 각 프로그램 라이브러리와 보기에 매우 어렵다.예를 들어 urql은 일시적으로 대응했지만 Revert가 React 외부 상태 관리층을 보유한 프로그램 라이브러리(form계,fetch계 등 사실상 상당수)가 어느 정도까지 대응할 필요가 있는지 밝혀진 것은 애매하다.
참조:
논점 4:startTransition과의 관계
논점이 아닐 수도 있지만 이해하기 어려운 면이 있으니 설명해 주세요.
간단하게 생각해봐.
초기 데이터 추출: loading에서 Suspense를 사용하여 fallback 표시
재취득: startTransition을 사용하면 재취득 시 재로드 상태에 따라suspense는fallback을 표시하지 않고 새 데이터가 오기 전에 오래된 데이터를 보냅니다.
참조:
끝말
계속 이용하면 새로운 논점이 나오기 때문에 수시로 보완할 계획이다.혹시 눈치채신 분 있으면 꼭 메시지를 남겨주세요.
Reference
이 문제에 관하여(React Suspense의 논점), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/ynakamura/articles/dc4d5e3929bed5텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)