[250328] TIL
오늘 한 일
상태(State) 관리 차이점
클래스형 컴포넌트
- this.state, this.setState() 사용
- 모든 상태는 state 객체안에 저장
- 항상 this 키워드를 사용해야한다.
- setState()는 객체를 병합한다.
class Counter extends React.Component {
constructor(props) {
super(props);
// state 초기화
this.state = {
count: 0,
name: '홍길동'
};
}
incrementCount = () => {
// setState로 상태 업데이트
this.setState({ count: this.state.count + 1 });
}
render() {
return (
<div>
<p>카운트: {this.state.count}</p>
<p>이름: {this.state.name}</p>
<button onClick={this.incrementCount}>증가</button>
</div>
);
}
}
함수형 컴포넌트
- useState hook 사용
- hook이란 리액트에서 상태관리와 생명주기 기능을 사용할 수 있게 해주는 도구
- 리액트 16.8 버전에서 도입
- 각 상태를 독립적으로 관리할 수 있음
- this 키워드가 필요 없어 더 직관적
- 상태 업데이트 함수는 이전 상태를 완전히 대체함 (병합 아님)
function Counter() {
// 각 상태를 개별적으로 선언
const [count, setCount] = useState(0);
const [name, setName] = useState('홍길동');
const incrementCount = () => {
// 상태 업데이트 함수 호출
setCount(count + 1);
};
return (
<div>
<p>카운트: {count}</p>
<p>이름: {name}</p>
<button onClick={incrementCount}>증가</button>
</div>
);
}
생명주기 (Lifecycle) 관리 차이점
클래스형 컴포넌트
- 명확한 생명주기 메서드를 제공한다.
- 각 단계별로 다른 메서드를 사용함
- 코드가 분산되어 있어 관련 로직이 여러 메서드에 나뉘어 있을 수 있다.
class DataFetcher extends React.Component {
constructor(props) {
super(props);
this.state = { data: null, loading: true };
}
// 마운트 시 호출
componentDidMount() {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => {
this.setState({ data, loading: false });
});
}
// 업데이트 시 호출
componentDidUpdate(prevProps) {
if (prevProps.id !== this.props.id) {
this.setState({ loading: true });
fetch(`https://api.example.com/data/${this.props.id}`)
.then(response => response.json())
.then(data => {
this.setState({ data, loading: false });
});
}
}
// 언마운트 시 호출
componentWillUnmount() {
// 정리 작업 (예: 이벤트 리스너 제거, 타이머 정리)
console.log('컴포넌트가 제거됩니다');
}
render() {
return (
<div>
{this.state.loading ? '로딩 중...' : this.state.data}
</div>
);
}
}
함수형 컴포넌트
- useEffect hook 사용해서 생명주기 관리
- 의존성 배열로 실행 시점을 제어함
- 관련 로직을 하나의 useEffect 안에 모을 수 있어 응집도가 높습니다.
function DataFetcher({ id }) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
// 의존성 배열이 빈 배열일 때 - componentDidMount와 유사
useEffect(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => {
setData(data);
setLoading(false);
});
// 반환되는 함수는 componentWillUnmount와 유사
return () => {
console.log('컴포넌트가 제거됩니다');
};
}, []); // 빈 배열은 마운트와 언마운트 시에만 실행
// id가 변경될 때마다 실행 - componentDidUpdate와 유사
useEffect(() => {
if (id) {
setLoading(true);
fetch(`https://api.example.com/data/${id}`)
.then(response => response.json())
.then(data => {
setData(data);
setLoading(false);
});
}
}, [id]); // id가 변경될 때만 실행
return (
<div>
{loading ? '로딩 중...' : data}
</div>
);
}
그 외 차이점
메모리 사용과 성능
- 함수형 컴포넌트는 일반적으로 더 가볍고, 메모리를 덜 사용한다.
- 클래스형 컴포넌트는 인스턴스를 생성하므로 더 무거울 수 있다.
코드 가독성과 유지보수
- 함수형 컴포넌트는 일반적으로 코드가 더 짧고 간결함
- 클래스형 컴포넌트는 this 바인딩 문제로 혼란을 줄 수 있음
로직 재사용
- 함수형 컴포넌트는 커스텀 훅을 통해 로직을 쉽게 재사용 가능
- 클래스형은 HOC(고차 컴포넌트)나 render props 패턴을 사용해야함
Leave a comment