반응형
왜 ErrorBoundary를 쓰나요
- 선언적 에러 핸들링
- 자바스크립트 런타임 에러와 비동기 에러를 동시 처리
- 하위 컴포넌트 에러를 상위 컴포넌트에서 처리
사용방법 1 : 직접 구현하기
에러바운더리는 현재 클래스 컴포넌트만 사용할 수 있음
1. 에러바운더리 컴포넌트 만들기
static getDerivedStateFromError 메소드를 구현함. (error) 꺼내옴
props의 FallbackComponent에 error를 전달후 렌더링
에러 없으면 children 렌더링
class ErrorBoundary extends React.Component {
state = {error: null}
static getDerivedStateFromError(error) {
return {error}
}
render() {
const {error} = this.state
if (error) {
return <this.props.FallbackComponent error={error} />
}
return this.props.children
}
}
2. FallbackComponent 만들기
function ErrorFallback({error}) {
return (
<div role="alert">
There was an error:{' '}
<pre style={{whiteSpace: 'normal'}}>{error.message}</pre>
</div>
)
}
3. key속성을 통해 ErrorBoundary Re-mount(에러초기화)
function App() {
const [pokemonName, setPokemonName] = React.useState('')
function handleSubmit(newPokemonName) {
setPokemonName(newPokemonName)
}
return (
<div className="pokemon-info-app">
<PokemonForm pokemonName={pokemonName} onSubmit={handleSubmit} />
<hr />
<div className="pokemon-info">
/** 여기 주목 **/
<ErrorBoundary key={pokemonName} FallbackComponent={ErrorFallback}>
<PokemonInfo pokemonName={pokemonName} />
</ErrorBoundary>
</div>
</div>
)
}
참고 : PokemonInfo 컴포넌트
react-hooks/pokemon.js at main · kentcdodds/react-hooks (github.com)
react-hooks/06.extra-5.js at main · kentcdodds/react-hooks (github.com)
function PokemonInfo({pokemonName}) {
const [state, setState] = React.useState({
status: 'idle',
pokemon: null,
error: null,
})
const {status, pokemon, error} = state
React.useEffect(() => {
if (!pokemonName) {
return
}
setState({status: 'pending'})
fetchPokemon(pokemonName).then(
pokemon => {
setState({status: 'resolved', pokemon})
},
error => {
setState({status: 'rejected', error})
},
)
}, [pokemonName])
if (status === 'idle') {
return 'Submit a pokemon'
} else if (status === 'pending') {
return <PokemonInfoFallback name={pokemonName} />
} else if (status === 'rejected') {
// this will be handled by an error boundary
throw error
} else if (status === 'resolved') {
return <PokemonDataView pokemon={pokemon} />
}
throw new Error('This should be impossible')
}
function ErrorFallback({error}) {
return (
<div role="alert">
There was an error:{' '}
<pre style={{whiteSpace: 'normal'}}>{error.message}</pre>
</div>
)
}
사용방법 2 : 남이 만든 라이브러리 가져다 쓰기
react-error-boundary를 사용한다.
react-hooks/06.extra-8.js at main · kentcdodds/react-hooks (github.com)
1. 아까 만든 클래스 컴포넌트를 지운다
2. (Option) ErrorFallback 컴포넌트에서 ErrorBoundary를 리셋시킬 수 있는 resetErrorBoundary함수를 사용한다.
function ErrorFallback({error, resetErrorBoundary}) {
return (
<div role="alert">
There was an error:{' '}
<pre style={{whiteSpace: 'normal'}}>{error.message}</pre>
<button onClick={resetErrorBoundary}>Try again</button>
</div>
)
}
3. 사용하는 곳을 다음과 같이 바꾼다.
fallbackComponent는 동일
onReset(new) : 에러가 리셋될 때 호출할 함수 설정
resetKeys(new) : 클래스 컴포넌트의 key에 대응. 의존성 배열처럼 사용.
import {ErrorBoundary} from 'react-error-boundary'
function App() {
const [pokemonName, setPokemonName] = React.useState('')
function handleSubmit(newPokemonName) {
setPokemonName(newPokemonName)
}
// error reset되면 호출할 함수
function handleReset() {
setPokemonName('')
}
return (
<div className="pokemon-info-app">
<PokemonForm pokemonName={pokemonName} onSubmit={handleSubmit} />
<hr />
<div className="pokemon-info">
<ErrorBoundary
FallbackComponent={ErrorFallback} // Fallback시 렌더링할 컴포넌트.
onReset={handleReset}
resetKeys={[pokemonName]} // 클래스 컴포넌트의 key와 동일한 역할.
>
<PokemonInfo pokemonName={pokemonName} />
</ErrorBoundary>
</div>
</div>
)
}
반응형
'FrontEnd' 카테고리의 다른 글
Node.js 메모리 누수 찾기 관련 게시글 모음 (0) | 2021.12.05 |
---|---|
제어의 역전(IOC : Inversion of Control) in React (0) | 2021.12.04 |
[Epic React] async 훅 사용 시 하나의 state를 사용하는 이유 (0) | 2021.12.04 |
[Epic React] useCallback과 안전한 비동기 훅 만들기 (0) | 2021.12.04 |
[Epic React] useDebug으로 custom hook debugging (0) | 2021.12.04 |