클래스형 컴포넌트와 함수형 컴포넌트의 차이

Nyeongs·2023년 4월 6일

React

목록 보기
3/3
post-thumbnail

클래스형 컴포넌트와 함수형 컴포넌트의 차이

클래스형 컴포넌트함수형 컴포넌트
state 사용 가능 여부가능불가능했지만, 리액트 버전 16에 도입된 hook을 통해 사용 가능해짐
라이프 사이클 메서드 사용 가능 여부가능불가능했지만, 리액트 버전 16에 도입된 hook을 통해 라이프 사이클마다 원하는 동작을 할 수 있게 됨
메모리함수형 컴포넌트보다 메모리를 조금 더 차지함클래스형 컴포넌트보다 메모리를 조금 덜 차지함
재사용 가능한 로직 구현render props, 고차 컴포넌트 패턴으로 구현하고, 라이프 사이클 메서드 기준으로 컴포넌트를 나눠야 하기 때문에 버그가 쉽게 발생하고 무결성 확보가 어려움Hook을 활용하여 로직을 추상화할 수 있기 때문에 로직 기준으로 컴포넌트를 잘게 쪼갤 수 있어 코드 추적과 무결성 확보가 용이함
코드의 간결성
사용 권장권장하지 않음공식 문서에서는 함수형 컴포넌트와 훅을 함께 사용할 것을 권장

컴포넌트의 형태

클래스형 컴포넌트

// class 키워드로 시작    // Component로 상속받음
class MyComponent extends Component {
  // render() 메서드로 jsx 반환
  render() {
    return (
      ...
    );
  }
}

함수형 컴포넌트

// 함수로 작성
const MyComponent = () => {
	// return 문으로 jsx 반환
  return (
		...
  );
}

state 사용 방식

class형 컴포넌트

class형 컴포넌트에서 state는 항상 객체 형태
//constructor 내부에서 초깃값 설정

constructor(props) {
	super(props)
	this.state = {
		....
	}
}

// 또는 직접 초깃값 설정

class myComponent extends Component {
	state = {
		....
	}
}
// this로 state 조회

this.state.myState;
// this.setState로 state 값 변경

this.setState({변경할 값})

함수형 컴포넌트

useState hook 사용
// 초깃값 설정 및 state 조회

const [state, setState] = useState(초기값);
// state 값 변경

setState(변경할 값)

props

클래스형 컴포넌트

// this 키워드로 props 조회
const { props1, props2 } = this.props;
// defaultProps 설정
MyComponent.defaultProps = {
  ...
}

// 또는 static 키워드와 함께 선언
static defaultProps = {
  ...
}

함수형 컴포넌트

const MyComponent = ({props1, props2}) => {
	...
}

이벤트 핸들링

클래스형 컴포넌트

class myComponent extends Component {
	// 생성자 메서드에서 핸들러를 bind 하거나,
  constructor(props) {
    super(props);
    this.handleClick= this.handleClick.bind(this);
  }

	handleChange() {
		....
	}


	// bind 메서드를 사용하지 않고 화살표 함수 사용
	handleChange = () => {
		....
	}

	render() {
		// this로 핸들러 할당
		<input onChange={this.handleChange}/>
	}
}

함수형 컴포넌트

const myComponent = () => {
	// const 키워드로 선언
	const handleChange = () => {
		...
	}

	return (
		// 핸들러 할당
		<input onChange={handleChange}/>
	)
}

LifeCycle 메서드

클래스형 컴포넌트

1. 마운트

  1. constructor
// 1. constructor
// 컴포넌트 생성자 메서드
// 가장 먼저 실행(render 전에 호출)

constructor(props) {
	super(props)
}

  1. getDerivedStateFromProps
// props로 받아온 것을 state에 넣어주고 싶을 때 사용
// render 메서드 호출 직전에 호출됨

static getDerivedStateFromProps(nextProps, prevState) {
	...
}

  1. render
// 컴포넌트를 렌더링하는 메서드
// 사이드 이펙트를 발생시키면 안 됨

render() {
	...
}

  1. componentDidMount
// render 메서드의 첫 번째 반환값이 실제 돔에 반영된 직후 호출
// 외부 api호출, DOM 에 관련된 작업

componentDidMount() {
	...
}

2. 업데이트

  1. shouldComponentUpdate
// 컴포넌트의 리렌더링 여부를 결정
// 컴포넌트 최적화 시 활용
// props나 state가 바뀌었을 때 호출됨

shouldComponentUpdate(nextProps, nextState) {
  return true;
  // 기본값은 true
  // false를 반환하면 업데이트 X
}

  1. render

  1. getSnapshotBeforeUpdate
// 렌더링 결과가 실제 돔에 반영되기 직전에 호출
getSnapshotBeforeUpdate(prevProps, prevState) {
	...
}

  1. componentDidUpdate
// 업데이트 단계에서 마지막으로 호출됨
// 가상 돔이 실제 돔에 반영된 후 호출됨
// 새로 반영된 돔의 상태값을 가장 빠르게 가져올 수 있는 메서드

componentDidUpdate(prevProps, prevState, snapshot) {
	// 3번째 파라미터로 getSnapshotBeforeUpdate에서 반환한 값을 조회
}

3. 언마운트

  1. componentWillUnmount
// 컴포넌트가 화면에서 사라지기 직전에 호출
// 주로 사전에 해당 컴포넌트에 등록했었던 이벤트 및 연관 외부 라이브러리 호출 등을 제거

componentWillUnmount() {
	...
}

함수형 컴포넌트

  • useEffect
useEffect(() => {
  // 렌더링 될 때마다 실행:
  // 1. 마운트(렌더 직후)
  // 2. 업데이트
  //    - 의존성 배열이 없다면 업데이트 될 때마다
  //    - 의존성 배열이 비어있다면 업데이트 시 실행X
  //    - 의존성 배열의 값이 있다면 해당 값이 변경될 때마다

  return () => {
    // 컴포넌트의 언마운트 직전에 실행
  };
}, []);

  • useCallback, useMemo
// 리렌더링 여부를 결정
// 컴포넌트 최적화 시 활용

const cachedFn = useCallback(() => {
	...
}, [])

const cachedValue = useMemo(() => {
	...
},[])

  • useLayoutEffect
// 렌더링 결과가 실제 돔에 반영되기 직전에 호출

useLayoutEffect(() => {
	...
},[])


// 로직이 복잡할 경우 사용자가 변경된 레이아웃을 보는데까지 시간이 오래 걸린다는 단점이 있기 때문에,
// 기본적으로는 항상 useEffect만을 사용하는 것을 권장함.
// 하지만 첫 렌더링 시 보여지는 레이아웃과 보여줘야 하는 레이아웃이 달라 화면에 깜빡이는 발생하는 상황에서는 useLayoutEffect를 사용하는 것이 좋음.

참고

profile
발전하는 사람🌱

0개의 댓글