클래스형/함수형 컴포넌트

Voler Web·2022년 9월 8일

Word

목록 보기
19/23

  클래스형 컴포넌트

현재 시점에서는 자주 사용하지는 않는 컴포넌트로 아직 사용하는 기업은 있습니다

  • class 키워드로 시작
  • state, lifeCycle 관련 기능 사용이 가능하다.
  • 메모리 자원을 함수형 컴포넌트보다 조금 더 사용된다.
  • 임의 메서드를 정의할 수 있다.
  • props를 조회할 때 this 키워드를 사용하여 조회한다.
  • render() 함수를 사용하여 JSX를 반환한다

코드 예시

import React, { Component } from 'react';

class Hello extends Component {
  render() {
    const { color, name } = this.props;
    return (
      <div style={{ color }}>
        안녕하세요 {name}
      </div>
    );
}

export default Hello;

  함수형 컴포넌트

  • function 키워드로 시작
  • state, lifeCycle 관련 기능 사용이 가능하다. [hook을 통해 해결 가능]
  • 메모리 자원을 클래스 형 컴포넌트보다 덜 사용한다.
  • 컴포넌트 선언이 좀 더 편하다
  • return 문을 사용하여 JSX를 반환한다

코드 예시

import React from 'react';

function Hello({ color, name }) {
  return (
    <div style={{ color }}>
      안녕하세요 {name}
    </div>
  );

export default Hello;

1. state 값 사용 시 차이

state

  • 컴포넌트 내부에서 바뀔 수 있는 값

  Class 클래스형

  • this.state 초깃값 설정이 가능하다.
  • 클래스형 컴포넌트의 state는 객체 형식으로 생성된다.
/// 1
class Monsters extendes Component {
  constructor(props) {
     super(props);

     this.state  = {
       monsters: [],
       userInput: "",
     };
}
/// 2
class Monsters extendes Component {
    state = {
      monsters: [],
      userInput: "",
    }
  }
}


  • this.setState 함수로 state의 값을 변경할 수 있다
this.state = { monsters: [], userInput: "", };

onClick = {() => {
   this.setState({number: number * 1});
}}

  Function 함수형

  • 함수형 컴포넌트에서는 useState Hook으로 state를 사용한다.
  • useState Hook을 호출하면 배열이 반환된다.
  • 첫 번째 원소는 현재 상태, 두 번째 원소는 상태를 바꿔주는 함수
  • 상태 값을 객체 형식으로 저장이 가능하다
const [state,setState] = useState('');

setState('hello');

console.log(state) // 'hello'

2. props의 사용 차이

props

  • 부모 컴포넌트에서 전달받은 값
  • 읽기 전용 값으로 변경할 수 없습니다.

  Class 클래스형

  • this.props로 값을 불러올 수 있습니다.
class MyProps extends Component {
   render() {
      return (
         <div>
            안녕하세요 {this.props.name}
         </div>
      )
   }
}

구조 분해 할당으로 props를 이름으로 사용할 수 있습니다.

const {name} = this.props;
  <div>
    안녕하세요 {name}
  </div>

  Function 함수형

  • props를 불러 올 필요 없이 호출 할 수 있다
function MyProps = ({ name }) => {
  return (
     <div> 
        안녕하세요 {name}
      </div>
  );
}

3. 이벤트 핸들링

  Class 클래스형

  • 함수 선언시 에로우 화살로 바로 선언이 가능하다.
  • 요소에서 적용하기 위해서는 this값을 붙여줘야 한다
handleChange = e => {
   this.setState({
     message: e.target.value 
   })
}

handleClick = () => {
   alert(this.state.message);
   this.setState({
     message:''
   })
}


render() {
  return (
    <div>
      <h1>이벤트 헨들링</h1>
      <input 
        type="text"
        name="message"
        placeholder="아무거나 입력하세요"
        value={this.state.message}
        onChange={this.handleChange}
       />
       <button onClick={this.handleClick}>확인</button>
     </div>
  )
}

  Function 함수형

  • 함수 선언문 , 함수 표현식으로 가능하다.
  • 요소에 적용하기 위해 this 값은 필요로 하지 않는다.
const onClick = () => {
  alert(message);
  setMessage('');
}

function onKeyPress() {
  if (e.key === "Enter") {
        onClick();
   }
}

return (
   <div>
     <h1>이벤트 KeyPress</h1>
     <input 
       type="text"
       name="message"
       placeholder="아무거나 입력해주세요"
       value={message}
       onChange={onChangeMessage}
       onKeyPress={onKeyPress}
     />
     <button onClick={onClick}>확인</button>
)

4. LifeCycle

LifeCycle(생명주기)

  • 컴포넌트가 실행,업데이트,제거가 될 때 특정한 이벤트들이 발생합니다.

  Class 클래스형

import React, { Component } from 'react';
import PropTypes from 'prop-types';

export default class Basic extends Component {
  static propTypes = {
    name: PropTypes.string.isRequired,
    birth: PropTypes.number.isRequired,
    lang: PropTypes.string,
  };

  static defaultProps = {
    lang: 'Javascript',
  };

  static contextTypes = {
    router: PropTypes.object.isRequired,
  };

  state = {
    hidden: false,
  };

  componentWillMount() {
    console.log('componentWillMount');
  }

  componentDidMount() {
    console.log('componentDidMount');
  }

  componentWillReceiveProps(nextProps) {
    console.log('componentWillReceiveProps');
  }

  shouldComponentUpdate(nextProps, nextState) {
    console.log('shouldComponentUpdate');
    return true / false;
  }

  componentWillUpdate(nextProps, nextState) {
    console.log('componentWillUpdate');
  }

  componentDidUpdate(prevProps, prevState) {
    console.log('componentDidUpdate');
  }

  componentWillUnmount() {
    console.log('componentWillUnmount');
  }

  onClickButton = () => {
    this.setState({ hidden: true });
    this.refs.hide.disabled = true;
  }

  render() {
    return (
      <div>
        <span>저는 {this.props.lang} 전문 {this.props.name}입니다!</span>
        {!this.state.hidden && <span>{this.props.birth}년에 태어났습니다.</span>}
        <button onClick={this.onClickButton} ref="hide">숨기기</button>
        <button onClick={this.context.router.goBack}>뒤로</button>
      </div>
    );
  }
}

Mount

  • 컴포넌트가 DOM에 장착되는 것

컴포넌트가 처음 실행될 때 그것을 Mount라고 표현합니다

1. state, context, defaultProps의 정보를 저장
2. componentWillMount - - -컴포넌트 장착 예정
3. render - - - 1번에서 받은 정보로 엘리멘트를 다 그림
4. componentDidMount - - - 정상적으로 장착 / DOM 접근 가능 단계

Props Update

  • Props가 변경됨을 감지

props가 업데이트될 때의 과정입니다.

1. componentWillReceiveProps - - - 업데이트된 props를 받을 예정
2. shouldComponentUpdate - - - 컴포넌트 업데이트 결정
3. componentWillUpdate - - - 컴포넌트 업데이트 중
4. render - - - 엘리멘트가 다시 그려짐
5. componentDidUpdate - - - 업데이트 완료 / 바뀌기 전 props 정보를 갖고 있음

State Update

  • State가 변경됨을 감지

this.setState 호출을 통해 state가 업데이트될 때의 과정입니다.
props update와 과정이 같지만, componentWillReceiveProps 메서드는 호출되지 않습니다.
그리고 메서드의 두 번째 인자로는 바뀔 state에 대한 정보를 가지고 있습니다.

1. shouldComponentUpdate - - - 컴포넌트 업데이트 결정
2. componentWillUpdate - - - 컴포넌트 업데이트 중
3. render - - - 엘리멘트가 다시 그려짐
4. componentDidUpdate  - - - 업데이트 완료 / 바뀌기 전 state 정보를 두 번째 인자로 갖고 있음

Unmount

  • 컴포넌트를 제거함
1. componentWillUnmount - - - 컴포넌트를 제거할 때 사용하는 이벤트

이 이후에 다른 이벤트는 없습니다. 제거 후 이벤트는 없으니까요.

  Function 함수형

함수형 컴포넌트는 useEffect() Hook을 이용하여 생명주기를 관리합니다,
hidden이라는 state가 있다고 가정하에 설명을 합니다.

useEffect(() => {
  console.log('hidden changed');
}, [hidden]);

컴포넌트가 첫 렌더링 될 때 한번 실행되고, 그다음부터는 hidden이 변경될 때마다 실행이 됩니다.
즉, componentDidMount와 componentDidUpdate가 합쳐진 셈입니다.

componentWillUnmount의 역할도 함께 할 수 있습니다. return으로 함수를 제공하면 됩니다.

useEffect(() => {
  console.log('hidden changed');
  return () => {
    console.log('hidden이 바뀔 예정입니다.');
  };
}, [hidden]); 

데이터의 라이프 사이클이 하나로 합쳐진 셈이며 이것을 활용해 setTimeout 한 것을 return에서 clearTimeout을 할 수도 있습니다.

데이터가 여러 개라면 여러 개의 useEffect() 훅을 이용하여 적용하면 됩니다.

Mount 될 때 처음 한 번만 실행하고 싶다면 빈 배열을 넣어주면 됩니다.
deps가 없어 변경되는 것이 없으므로 처음 한 번만 실행되고 재실행 되지 않습니다.
단, 컴포넌트가 언마운트 될 때는 return의 함수가 실행됩니다.

useEffect(() => {
  console.log('mounted');
  return () => {
    console.log('unmount');
  }
}, []); 

반대로 컴포넌트가 리렌더링 될 때마다 실행하게 할 수 있습니다. 두 번째 배열을 아예 넣지 않으면 데이터와 관련 없이 리렌더링 시마다 실행됩니다.

useEffect(() => {
  console.log('rerendered!');
});

만약 componentDidUpdate의 역할만 하고 싶다면 componentDidMount와 componentDidUpdate의 역할을 동시에 수행하는 useEffect라 componentDidMount의 역할을 제거해야 합니다. 이를 위해서는 useRef라는 훅이 필요합니다.

결과

1. 함수형은 클래스형보다 선언하기 쉽다
2. 클래스형은 render로 함수형은 return으로 JSX를 반환한다.
3. state 사용시 클래스는 this.state로 함수는 useState 훅을 사용한다.
4. props 사용시 클래스는 this.props로 불러와야 하고 함수는 그냥 props를 사용하면 된다. 다만 객체로 받아야함 ({name})
5. 이벤트 핸들링시 클래스형은 에로우 화살로 바로 선언 함수형은 선언문이나 표현식으로 선언해야함
6. 생명주기는 class는 자체적인 생명주기 관리가 가능하고 , function은 useEffet() 훅으로 관리가 가능하다.

출처 : sdc337dc.log
출처 : Koras02코딩웹:티스토리
출처 : 제로초 React 생명주기

profile
공부하려 끄적이는 velog

0개의 댓글