이전 게시글 리액트 라이프사이클 이해하기에 이어서..
라이프사이클 메서드들을 여러개 사용해서 컴포넌트를 만들어볼 것이다.
컴포넌트 생성
LifeCycleSample 이라는 컴포넌트를 만들 것이다.
// src/LifeCycleSample.tsx
import React, { useState, useEffect, useRef } from "react";
type LifeCycleSampleProps = {
color: string;
};
const LifeCycleSample = ({ color }: LifeCycleSampleProps) => {
const [number, setNumber] = useState(0);
const [prevColor, setPrevColor] = useState<string | null>(null);
const myRef = useRef<HTMLHeadingElement>(null);
useEffect(() => {
console.log("componentDidMount");
return () => {
console.log("componentWillUnmount");
};
}, []);
useEffect(() => {
console.log("getDerivedStateFromProps");
if (color !== prevColor) {
setPrevColor(color);
if (myRef.current) {
myRef.current.style.color = color;
}
}
}, [color, prevColor]);
useEffect(() => {
console.log("componentDidUpdate");
if (myRef.current) {
myRef.current.style.transition = "0.5s";
myRef.current.style.transform = `rotate(${360 * number}deg)`;
}
}, [number]);
const handleClick = () => {
setNumber(number + 1);
};
return (
<div>
<h1 ref={myRef}>{number}</h1>
<p>color: {prevColor}</p>
<button onClick={handleClick}>더하기</button>
</div>
);
};
export default LifeCycleSample;
// src/App.tsx
import React from "react";
import LifeCycleSample from "./LifeCycleSample";
function App() {
return (
<div>
<LifeCycleSample color="000000" />
</div>
);
}
export default App;
이 코드는 부모 컴포넌트에게서 color 값을 받아서 state에 동기화한다. 그리고 Props 타입을 정의해서 타입 안에 color라는 문자열 타입 하나를 필드로 가지고 있다. 그리고 함수형 컴포넌트에서는 이 Props 타입을 사용한다. 함수의 첫 번째 매개변수로 전달되며, 함수 내부에서는 useState 훅을 사용해 number라는 상태값을 정의하고, useRef 훅을 사용해 myRef라는 변수를 정의해준다.
그리고 useEffect 훅을 사용해 컴포넌트의 생명주기 메소드를 구현한다. useEffect 훅은 두 번째 매개변수로 전달된 배열의 값이 변경될 때마다 호출된다. 이 예제에서는 첫 번째 useEffect 훅에서 컴포넌트가 처음 마운트될 때만 호출되는 코드를 작성했고, 두 번째 useEffect 훅에서 color 값이 변경될 때 마다 호출되는 코드를 작성해주었다. 마지막 useEffect는 number 값이 변경될 때 마다 호출되는 코드를 작성해주었다.
결과를 보면, 부모 컴포넌트에서 color를 "000000"으로 설정해서 넘겨주었기 때문에, 버튼을 눌렀을 때 값은 변하지만 색은 검정색으로 계속 일정한 것을 확인할 수 있다.
그렇다면, 이 색상을 바꿀 수 있는 코드를 작성해보자.
부모 컴포넌트 설정
import React from "react";
import LifeCycleSample from "./LifeCycleSample";
import { useState } from "react";
function getRandomColor(): string {
return "#" + Math.floor(Math.random() * 16777215).toString(16);
}
function App() {
const [color, setColor] = useState("#000000");
function handleClick() {
setColor(getRandomColor());
}
return (
<div>
<button onClick={handleClick}>랜덤 색상</button>
<LifeCycleSample color={color} />
</div>
);
}
export default App;
App 컴포넌트를 수정해서 랜덤 색상을 설정할 수 있는 함수와 버튼을 구현했다.
먼저 getRandomColor 함수는 무작위 색상을 생성하는 함수이다. 이 함수는 랜덤 색상을 만들기 위해 Math.random() 함수를 사용한다.
App 컴포넌트는 useState 훅을 사용해서 color 상태 값을 가지고 있다. color 상태는 초기값으로 "#000000"(검정색)을 가지며, handleClick 함수는 랜덤 색상 버튼을 클릭하면 color값을 getRandomColor()로 생성된 새로운 무작위 색상으로 변경한다.
렌더링이 잘 되었는지 확인했다면, 브라우저 검사 페이지를 열어서 랜덤 색상 버튼과 더하기 버튼을 번갈아가며 눌러보자. 버튼에 따라 라이프사이클 메서드의 실행이 다른것을 확인해보자.
에러 핸들링
만약, 생성한 컴포넌트의 렌더링 부분에서 의도적으로 에러를 발생시켜보자. LifeCycleSample 컴포넌트의 return 부분에서 의도적으로 에러를 한번 발생시켜 보면, 에러가 발생하고 빈 페이지가 나타날 것이다.
const LifeCycleSample = ({ color }: LifeCycleSampleProps) => {
// 이전 코드
return (
<div>
{this.props.missing.value}
<h1 ref={myRef}>{number}</h1>
<p>color: {prevColor}</p>
<button onClick={handleClick}>더하기</button>
</div>
);
};
에러 발생은 현재 개발중이기 때문에 나오는 화면이고, 빈 화면은 사용자가 보는 화면이다. 이럴때는 에러가 발생했다고 사용작에게 인지를 시켜주어야 한다.
에러를 잡아주는 ErrorBoundary라는 컴포넌트를 생성해보자.
import React, { useState, useEffect, ReactNode } from "react";
interface Props {
children: ReactNode;
}
interface ErrorInfo {
componentStack: string;
}
function ErrorBoundary(props: Props) {
const [error, setError] = useState(false);
useEffect(() => {
function handleError(event: ErrorEvent) {
setError(true);
console.log({ error: event.error, info: event });
}
window.addEventListener("error", handleError);
return () => window.removeEventListener("error", handleError);
}, []);
if (error) return <div>에러가 발생했습니다!</div>;
return <>{props.children}</>;
}
export default ErrorBoundary;
위 코드는 자식 컴포넌트들에서 발생하는 에러를 캐치하고 처리할 수 있는 컴포넌트이다.
useState 훅을 사용해서 error 상태를 초기화한다. useEffect 훅을 사용해 컴포넌트가 마운트되면 window.addEventListener를 호출해서 전역 객체인 window의 에러 이벤트를 감지한다.
에러 이벤트가 발생하면 handleError 함수가 실행되어 setError 함수를 호출하고, error 상태를 true로 변경한다.
변경된 error 상태를 토대로 div 요소에 에러가 발생했다는 텍스트를 표시해준다.
이 컴포넌트로 App 컴포넌트의 LifeCycleSample 컴포넌트를 감싸주자.
return (
<div>
<button onClick={handleClick}>랜덤 색상</button>
<ErrorBoundary>
<LifeCycleSample color={color} />
</ErrorBoundary>
</div>
);
다시 렌더링해보면 에러가 발생했다는 문구가 뜰 것이다.
라이프사이클 메서드는 컴포넌트 상태에 변화가 있을 때마다 실행하는 메서드이다. 이 메서드들은 서드파티 라이브러리를 사용하거나 DOM을 직접 건드려야하는 상황에서 유용하다.
'WEB > React' 카테고리의 다른 글
리액트 CSS 사용하기 [react/css/typescript] (0) | 2023.03.17 |
---|---|
리액트 Hooks 이해하기 [react/hooks/typescript] (0) | 2023.03.15 |
리액트 라이프사이클 이해하기 [react/life cycle/typescript] (0) | 2023.03.13 |
리액트 컴포넌트 반복 사용하기 [react/component/typescript] (0) | 2023.03.12 |
리액트 DOM 네이밍 이해하기 (0) | 2023.03.12 |