Skip to Content
Suspensive v3를 준비하고 있습니다. 🚀 더보기
문서보기@suspensive/reactv2로 마이그레이션하기

v2로 마이그레이션하기

새로운 기능

새로운 wrap 빌더 #270

컴포넌트를 <Suspense/>, <ErrorBoundary/>, <ErrorBoundaryGroup/>으로 한번에 래핑하는 새로운 기능입니다.

<Suspense/>, <ErrorBoundary/>, <ErrorBoundaryGroup/> 등의 경우 많은 사람들이 hoc를 사용하여 이러한 구성 요소를 구성 요소 주위에 래핑합니다. 이 컴포넌트들은 children에 어떤 처리를 요하기 때문입니다. 그래서 컴포넌트를 불필요하게 나누지 않고 depth를 만들지 않기 위해 각 interface를 위한 hoc인 withErrorBoundary, withErrorBoundaryGroup, withSuspense를 사용하지만 각 hoc를 조합해서 사용하는 경우도 자주 발생하면서 가독성 또한 개선할 필요가 있었습니다. 이를 개선하기 위해 wrap을 제공하기로 했습니다.

import { wrap } from '@suspensive/react' import { useSuspenseQuery } from '@suspensive/react-query' const Example = wrap .ErrorBoundaryGroup({ blockOutside: false }) .ErrorBoundary({ fallback: ({ error }) => <>{error.message}</>, onError: logger.log, }) .Suspense({ fallback: <>loading...</>, clientOnly: true }) .on(() => { const query = useSuspenseQuery({ queryKey: ['key'], queryFn: () => api.text(), }) return <>{query.data.text}</> })

새로운 <ErrorBoundary/>shouldCatch prop #569

Suspensive의 <ErrorBoundary/>는 children에서 발생된 모든 thrown error를 잡아낼 수 있습니다. 하지만 모든 thrown error를 잡아내기 때문에 <ErrorBoundary/>를 사용할 때 더 좁은 위치에 <ErrorBoundary/>를 놓는 것을 고민하게 되었습니다. 이 때문에 어떤 Error를 잡아내야 할지 설정할 수 있는 shouldCatch라는 새 prop을 ErrorBoundary에 추가하게 되었습니다.

ErrorBoundary shouldCatch example

  1. shouldCatch: ErrorConstructor
import { ErrorBoundary } from '@suspensive/react' class CustomError extends Error {} const Example = () => { return ( <ErrorBoundary fallback={({ error }) => <>RestError: {error.message}</>}> <ErrorBoundary shouldCatch={CustomError} onError={logOnCustomError} fallback={({ error }) => <>CustomError: {error.message}</>} > <ThrowErrorComponent /> </ErrorBoundary> </ErrorBoundary> ) }
  1. shouldCatch: callback
import { ErrorBoundary } from '@suspensive/react' class CustomError extends Error {} const Example = () => { return ( <ErrorBoundary fallback={({ error }) => <>RestError: {error.message}</>}> <ErrorBoundary shouldCatch={(error) => error instanceof CustomError} onError={logOnCustomError} fallback={({ error }) => <>CustomError: {error.message}</>} > <ThrowErrorComponent /> </ErrorBoundary> </ErrorBoundary> ) }
  1. shouldCatch: boolean
import { ErrorBoundary } from '@suspensive/react' class CustomError extends Error {} const Example = () => { return ( <ErrorBoundary fallback={({ error }) => <>RestError: {error.message}</>}> <ErrorBoundary shouldCatch={new Date().toISOString() > '2024-01-01T00:00:00.000Z'} onError={logOnErrorAfter2024} fallback={({ error }) => <>ErrorAfter2024: {error.message}</>} > <ThrowErrorComponent /> </ErrorBoundary> </ErrorBoundary> ) }

새로운 <ErrorBoundary.Consumer/>, <ErrorBoundaryGroup.Consumer/> 컴포넌트 #610

이 컴포넌트는 jsx에서 useErrorBoundary, useErrorBoundaryGroup을 인라인으로 사용할 수 있습니다.

import { ErrorBoundary, ErrorBoundaryGroup } from '@suspensive/react' const Example = () => { return ( <ErrorBoundaryGroup> <ErrorBoundaryGroup.Consumer> {({ reset }) => <button onClick={reset}>reset all</button>} </ErrorBoundaryGroup.Consumer> <ErrorBoundary fallback={({ error }) => <>{error.message}</>}> <ErrorBoundary.Consumer> {({ setError }) => ( <button onClick={() => setError(new Error('error message'))}> setError </button> )} </ErrorBoundary.Consumer> </ErrorBoundary> </ErrorBoundaryGroup> ) }

BREAKING CHANGES 처리하기

<AsyncBoundary/> 제거

v2에서는 <AsyncBoundary/>를 제거했습니다. #295

<AsyncBoundary/>는 내부적으로 <ErrorBoundary/>를 사용하기 때문에 useErrorBoundary와 함께 사용할 수 있으며 <ErrorBoundaryGroup/>의 영향을 받습니다. 우리는 라이브러리 사용자를 위한 유지 관리 및 인터페이스 통합에 더 좋을 것이라고 믿고 이 구성 요소를 v2에서 제거하기로 결정했습니다.

<AsyncBoundary/>의 기능은 두 컴포넌트(<Suspense/>, <Errorboundary/>)를 하나씩 래핑하는 것입니다. 그러면 이렇게 2개로 나눌 수 있습니다.

+ import { Suspense, Errorboundary } from '@suspensive/react' - import { AsyncBoundary } from '@suspensive/react' + <Errorboundary fallback={<Error />} onError={onError} onReset={onReset}> + <Suspense fallback={<Loading />}> + <Children /> + </Suspense> + </Errorboundary> - <AsyncBoundary pendingFallback={<Loading />} rejectedFallback={<Error />} onError={onError} onReset={onReset}> - <Children /> - </AsyncBoundary>

withSuspense, withDelay, withErrorboundary, withErrorBoundaryGroup 제거

이러한 모든 hoc는 v2의 새로운 hoc 빌더 wrap으로 아름답게 대체될 수 있습니다.

+ import { wrap } from '@suspensive/react' - import { withSuspense, withErrorBoundary, withErrorBoundaryGroup } from '@suspensive/react' + const Example = wrap + .ErrorBoundaryGroup({ blockOutside: false }) + .ErrorBoundary({ fallback: ({ error }) => <>{error.message}</>, onError: logger.log }) + .Suspense({ fallback: <>loading...</>, clientOnly: true }) + .on(() => { + const query = useSuspenseQuery({ + queryKey: ['key'], + queryFn: () => api.text(), + }) + return <>{query.data.text}</> + }) - const Example = withErrorBoundaryGroup( - withErrorBoundary( - withSuspense( - () => { - const query = useSuspenseQuery({ - queryKey: ['key'], - queryFn: () => api.text(), - }) - return <>{query.data.text}</> - }, - { fallback: <>loading...</>, clientOnly: true } - ), - { fallback: ({ error }) => <>{error.message}</>, onError: logger.log } - ), - { blockOutside: false } - )
+ import { wrap } from '@suspensive/react' - import { withSuspense } from '@suspensive/react' + const Example = wrap + .Suspense({ + fallback: <>loading...</>, + clientOnly: true, + }) + .on(() => { + const query = useSuspenseQuery({ + queryKey: ['key'], + queryFn: () => api.text(), + }) + return <>{query.data.text}</> + }) - const Example = withSuspense( - () => { - const query = useSuspenseQuery({ - queryKey: ['key'], - queryFn: () => api.text(), - }) - return <>{query.data.text}</> - }, - { - fallback: <>loading...</>, - clientOnly: true, - } - )

<ErrorBoundaryGroup.Reset/> 제거

<ErrorBoundaryGroup.Reset/>은 내부적으로 useErrorBoundaryGroup을 사용합니다. 그래서 우리는 이를 Context.Consumer와 같은 것으로 변경하면 React 개발자가 이 컴포넌트의 동작을 더 쉽게 이해할 수 있을 것이라고 생각했습니다. 이름을 <ErrorBoundaryGroup.Consumer/>로 변경하고 인터페이스를 Context.Consumer와 동일하게 유지했습니다.

import { ErrorBoundaryGroup } from '@suspensive/react' const Example = () => { return ( <ErrorBoundaryGroup> - <ErrorBoundaryGroup.Reset trigger={(group) => <button onClick={group.reset}>reset all</button>} /> + <ErrorBoundaryGroup.Consumer> + {(group) => <button onClick={group.reset}>reset all</button>} + </ErrorBoundaryGroup.Consumer> </ErrorBoundaryGroup> ) }

defaultOptionsSuspensivedefaultProps로 이름 변경

import { ErrorBoundaryGroup } from '@suspensive/react' const suspensive = new Suspensive({ - defaultOptions: { + defaultProps: { suspense: { fallback: 'default loading...', }, }, })

<Suspense.CSROnly/><Suspense clientOnly/>를 이름 변경(prop으로)

import { Suspense } from '@suspensive/react' const Example = () => { return ( - <Suspense.CSROnly fallback={<>loading...</>}> + <Suspense clientOnly fallback={<>loading...</>}> <>children</> </Suspense> ) }
수정된 날짜: