티스토리 뷰
리액트에서 임의로 js파일에 에러를 냈을 때, 브라우저에서는 아무런 요소도 볼 수 없고 흰 화면만 나타난다.
이유는 바로 "에러가 나면 스크립트가 실행을 멈추기 때문이다."
try - catch (+ finally)
예시 코드
- 에러를 임의적으로 만들어놓은 상황(상수에 다른 값을 재할당했습니다.)
const a = 1;
a = 2;
//위와 같이 임의로 에러를 냈을 때 에러난 부분부터 스크립트가 실행을 멈추고
// 아래의 코드는 실행이 안된다.
return (
<Container>
<div className="App" style={style.App}>
<MyHeader />
<h2 style={style.h2}>안녕하세용 😎</h2>
<b id="bold_text" style={style.bold_text}>
React.js
</b>
<Counter {...counterProps} />
<MyFooter />
</div>
</Container>
);
}
상수 a를 2로 변경하는 코드(에러코드) 이후의 멀쩡한 코드들은 그대로 브라우저에 렌더링시켜야 합니다.
이럴 때 에러 핸들링을 해줍니다.
에러가난 부분은 보여주지 않더라도 정상적으로 구동하는 애들은 보여주기 위해서 사용하는 것이 try- catch 입니다.
try {
const a = 1;
a = 2;
} catch (err) {
console.log(err);
}
이렇게 에러가 발생할 수도 있는 코드를 try내부의 코드로 넣어주고 catch의 블록 부분에 에러가 났을 때는 이걸 실행해줘 라는 에러 핸들링 코드를 적어줍니다.
-> 크롬 개발자 도구를 통해 콘솔을 확인해보면, TypeError(Assigment to constant variable) 가 붉은 글씨가 아니라 검정 글씨로 잘 찍힌 것을 확인할 수 있습니다.
⭐try catch 동작원리
try {
const a = 1;
a = 2;
} catch (err) {
console.log(err);
} finally {
console.log("끝났다.");
}
- try catch 구문은 에러가 나지 않았을 때는, catch 블록을 지나쳐 다음 코드를 진행합니다.
- 만약에 에러가 나든 안나든 마지막으로 항상 실행시켜주고 싶은 코드가 있다면 finally를 마지막에 붙여주어 원하는 동작을 finally의 블록 내부에 작성해주시면 됩니다.
⭐try catch는 모든 에러를 잡아주는 구문은 아니다.
try-catch 문은 오직 런타임 에러에서만 동작합니다.(읽을 수 있는 코드에서만 동작)
풀어서 설명하자면, 오직 읽을 수 있는 코드에 한하여 에러를 잡을 수 있다는 말입니다.
자바스크립트는 코드를 실행하기 전에 미리 코드를 읽어보고 해당 코드를 실행할 수 있는지 확인을 거칩니다.
이 과정에서 에러가 나면 parse-time에러가 납니다. 이런 parse-time에러는 try-catch로 잡을 수 없습니다.
*parse-time error를 간단히 말하자면 중괄호가 덜 닫혔거나 하는 것을 예시로 들 수 있습니다.
Error 객체 다루기(커스텀 에러)
try -catch의 catch 구문에서 받는 err를 typeof 로 찍어보면 객체임을 알 수 있다.
Error, SyntaxError, ReferenceError, TypeError 등 이런 에러들을 표준 에러 객체라고 합니다.
표준 에러 객체들은 전부 생성자를 사용해 직접 만들고 커스텀할 수 있습니다.
*생성자를 사용해 - > new 키워드 사용
try {
const a = 1;
a = 2;
} catch (err) {
console.log(typeof err); //object
// JS에서는 에러도 객체이다. 규격화돼있는 표준 에러 객체
예시
let my_new_error = new Error("에러랍니다!!!");
let my_custom_syntaxError = new SyntaxError("끾끼");
console.log(my_new_error, my_custom_syntaxError);
const new_error = new TypeError("message");
new_error.name = "타입에러";
console.log(new_error);// 타입에러: message
이렇게 생성자 함수의 인자값으로 message를 전달할 수도 있는데 에러객체의 이름을 따로 지정해주지않으면 생성자 객체의 명과 동일하게 기본으로 들어가게 됩니다. 저는 new_error.name을 "타입에러"로 커스텀하였습니다.
예시2 :
- 값을 받아오는 것에는 에러가 없으나 받아온 값이 20이 아닐 경우에도 자체적으로 에러라고 처리하고 싶다.
const data = { my_cat: "동글이", age: 20 };
try {
let cat_age = 29;
console.log(cat_age);
const age_error = new Error("동글이의 나이가 틀렸어요");
if (cat_age !== 20) {
console.log(age_error);
}
} catch (err) {
} finally {
console.log("끝났다.");
}
- 위의 코드는 try문에서 커스텀 에러를 발생시키고 있으므로 우리가 원하는 동작이 아닙니다.
- catch 문으로 넘기고 싶을 때는 try블록에서 throw 에러객체 를 통해 가능합니다.
const data = { my_cat: "동글이", age: 20 };
try {
let cat_age = 29;
console.log(cat_age);
const age_error = new Error("동글이의 나이가 틀렸어요");
if (cat_age !== 20) {
throw age_error; // 커스텀 에러 객체를 catch 구문으로 넘겨줬다.
}
} catch (err) {
console.log(err); //여기서 출력되는 것은 age_error 객체
} finally {
console.log("끝났다.");
}
🔥throw는 catch 블록에서도 사용이 가능합니다.
위의 경우에서 설명을 덧 붙이자면 만일 age_error가 아니라 값을 못 읽어와서 발생하는 에러가 있는 경우, 이 에러에 대해서도 처리를 해줘야 하는데 이럴 때는 try catch 구문 바깥에 try catch를 하나 더 씌워 내부 catch에서 에러를 throw 하면 외부 catch 구문에서 에러를 잡아낼 수 있습니다.
const data = { my_cat: "동글이", age: 20 };
try {
try {
let cat_age = data.age.age.age; //없는 값에 접근
console.log(cat_age);
const age_error = new Error("동글이의 나이가 틀렸어요");
age_error.name = "inner_err";
if (cat_age !== 20) {
throw age_error;
}
} catch (err) {
if (err.name !== "inner_err") {
throw err;
}
} finally {
console.log("끝났다.");
}
} catch (err) {
console.log("외부 catch:: ", err);
}
👾ErrorBoundary
자바스크립트에서는 에러가 나면 코드 실행을 멈춥니다.
리액트에서 자바스크립트 코드 실행이 멈추게 되면? 새하얀 화면만 보여지게 됩니다.
- 자바스크립트 에러가 전체 어플리케이션을 중단시키게 됩니다.
- 리액트는 이런 문제를 해결하기 위해 16버전부터 에러 바운더리라는 것을 도입했습니다.
: 에러 경계라고도 하며, 어떤 컴포넌트에서 자바스크립트 에러가 났을 시, 멈춰버린 컴포넌트 대신 fallback UI를 보여주도록 하는 리액트 컴포넌트를 말합니다.
- 하지만, Error Boundary는 생명주기 함수인 getDrivedStateFromError() 와 componentDidCatch()를 정의한 "클래스형 컴포넌트"를 만들어야 합니다. (둘 중 하나를 정의해서 만든 클래스형 컴포넌트가 에러 경계가 된다함)
- getDrivedStateFromError() - fallback UI보여주기 용
- componentDidCatch() - 에러 기록용
즉, ErrorBoundary는 클래스형 컴포넌트에서만 유효한 기능인데 우리는 함수형 컴포넌트를 사용하죠. 이럴 때 쓰라고 만들어진 패키지가 있습니다.
yarn add react-error-boundary
활용 예시 코드
src/ErrorB.js
import React from "react";
//에러 바운더리 라는 뜻
// 여기서 react-error-boundary 패키지를 쓸 것임
function ErrorB() {
const somethingData = "데이터아님";
if (somethingData !== "데이터") {
throw new Error("이건 데이터가 아닙니다.");
}
return <div>{somethingData}</div>;
}
export default ErrorB;
임의적으로 에러를 발생시키는 컴포넌트를 하나 만들어줍니다.
src/App.js
import ErrorB from "./ErrorB";
import { ErrorBoundary } from "react-error-boundary"; //에러 바운더리 컴포넌트를 가져옵니다.
// fallback으로 넣어줄 컴포넌트를 새로 만들고
const ErrorFallback = (err) => {
console.log(err);
return <div>에러 폴백입니다. </div>;
};
// App.js에 return 해주는 곳에 FallbackComponent로 만들어놓은 ErrorFallback 컴포넌트를 지정해줍니다.
return (
<ErrorBoundary FallbackComponent={ErrorFallback}>
<ErrorB />
</ErrorBoundary>
);
이렇게 하면 ErrorB 컴포넌트에서 에러가 생겼을 때 fallback컴포넌트로 빈화면이 아니라 대체 컴포넌트인 ErrorFallback이 화면에 보이게 됩니다. (*ErrorFallback도 컴포넌트라서 따로 js파일로 빼줘도 되는데 그냥 귀찮아서 내부에 같이 썼습니다. )
'Frontend > react.js' 카테고리의 다른 글
[React] Portal (0) | 2022.10.22 |
---|---|
[React | axios] axios interceptor 사용하기 (0) | 2022.10.22 |
[React] memoization, fetch, useReducer, contextAPI (0) | 2022.10.20 |
[React Router v6] 리액트 라우터 v6 & HOC (0) | 2022.10.07 |
[React JS] 리액트의 렌더링 (1) | 2022.09.23 |
- Total
- Today
- Yesterday
- 타입스크립트 장점
- is()
- 원티드 FE 프리온보딩 챌린지
- float 레이아웃
- 프리렌더링확인법
- aspect-ratio
- D 플래그
- 부트캠프항해
- 원티드 프리온보딩 프론트엔드 챌린지 3일차
- reactAPI
- 항해99프론트후기
- && 셸 명령어
- nvm 설치순서
- 프리온보딩 프론트엔드 챌린지 3월
- 틸드와 캐럿
- 형제 요소 선택자
- ~ ^
- getServerSideProps
- nvm경로 오류
- 원티드 3월 프론트엔드 챌린지
- grid flex
- Prittier
- 항해99추천비추천
- getStaticPaths
- 항해99프론트
- 원티드 프리온보딩 FE 챌린지
- fs모듈 넥스트
- tilde caret
- text input pattern
- 타입스크립트 DT
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |