안녕하세요!
오늘은 errorBoundary를 만드는 법에대해 알아보겠습니다.
componentDidCatch와 getDerivedStateFromError를 이용해 만들게됩니다.
지난 포스팅에서 마지막부분에 getDerivedStateFromError, componentDidCatch의 용도에 대해서 밝혔습니다.
바로 ErrorBoundary 컴포넌트를 만들어보겠습니다.
// App.js
function App() {
return (
<div className="App">
<ErrorBoundary>
<Counter></Counter>
</ErrorBoundary>
</div>
);
}
export default App;
App.js를 이렇게 수정해줍니다.
예외가 발생하면 getDerivedStateFromError, componentDidCatch메서드를 구현한 가장 가까운 부모 컴포넌트를 찾게됩니다.
따라서, ErrorBoundary컴포넌트를 최상위 컴포넌트로 만들면 생명주기에서 발생하는 모든 예외를 처리할 수 있습니다.
세분화하고 싶다면 나눌수도 있겠습니다.
이제 ErrorBoundary컴포넌트와 Counter컴포넌트를 만들어야합니다.
ErrorBoundary에서 두 생명주기 메서드를 구현하고, Counter컴포넌트에서는 임의로 에러를 발생시키는 코드를 작성합니다.
// ErrorBoundary.js
import React from "react";
export default class ErrorBoundary extends React.Component {
constructor (props) {
super(props);
this.state = {
error : null
}
}
static getDerivedStateFromError(error) {
return {error}
}
componentDidCatch(error, info) {
this.sendErrorToServer(error,info);
}
sendErrorToServer(error,info) {
console.log(`error : ${error}, info : ${JSON.stringify(info)}`)
// ...
}
render() {
const {error} = this.state
if(error) {
return <div>{error.toString()}</div>
}
return this.props.children;
}
}
componentDidCatch에서 원래는 에러를 서버로 보고하는 것이지만,간단하게 콘솔에 로그를 출력하는 메서드로 바꿨습니다.
getDerivedStateFromError에서는 에러정보를 화면에 출력하도록 state의 error에 추가합니다.
이어서 Counter컴포넌트입니다.
import React from "react";
export default class Counter extends React.Component {
constructor (props) {
super(props);
this.state = {
count:0
}
}
onClick = () => {
const {count} = this.state;
this.setState({count : count+1})
}
render() {
const {count} = this.state;
if (count >= 3) {
throw new Error('에러 발생!!')
}
return <button onClick = {this.onClick}> {`클릭하세요 ${count}`}</button>
}
}
컴포넌트의 버튼을 세번 클릭하면 state의 count가 3이상이 되면서 new Error을 throw합니다.
1.실행시킵니다.
npm start
2.이어서 버튼을 3번 클릭해 state.count를 3이상으로 만듭니다
정상적으로 에러가 출력됩니다!
몇 가지 알아둘 점은
리액트는 예외 발생시 ErrorBoundary 컴포넌트로 처리되지 않으면 모든 컴포넌트를 언마운트 합니다.
또, 이벤트처리 메서드에서 발생하는 에외는 ErrorBoundary 컴포넌트로 처리되지 않습니다. 이벤트 처리 메서드는 생명주기 메서드가 아니기 때문입니다. 방금전 코드에서는 render()생명주기 메서드에서 발생시켰었습니다.
이벤트처리 메서드에서 예외가 발생되는 경우에는 try~catch문으로 감싸줍니다.
이상으로 ErrorBoundary에 대한 포스팅을 마치겠습니다.