티스토리 뷰

Javascript/react

Component, props, state

chan20 2022. 1. 9. 16:19

함수형 컴포넌트

import React from 'react';
import './App.css';
 
function App() {
  const name = '리액트';
  return <div className="react">{name}</div>;
}
 
export default App;

클래스형 컴포넌트

import React, { Component } from 'react';
 
class App extends Component {
  render() {
    const name = 'react';
    return <div className="react">{name}</div>;
  }
}
 
export default App;

클래스형 컴포넌트와 함수형 컴포넌트의 차이점은 클래스형 컴포넌트의 경우 이후 배울 state 기능 및 라이프사이클 기능을 사용할 수 있다는 것과 임의 메서드를 정의할 수 있다는 것

 

함수형 컴포넌트의 장점

  • 클래스 컴포넌트보다 선언하기가 쉽다.
  • 메모리 자원도 덜 사용한다.
  • 파일 크기가 더 작다.

그럼 단점은?

  • state와 라이프사이클 API의 사용 불가( v16.8 이후부터 Hooks 기능이 도입으로 해결)

 

컴포넌트 만들기

  1. 파일 만들기
  1. 코드 작성
  1. 모듈 내보내기 및 불러오기

 

import React from 'react';
 
const MyComponent = () => {
  return <div>나의 새롭고 멋진 컴포넌트</div>;
};
 
export default MyComponent;

해당 함수형 컴포넌트에서는 () ⇒ {} 인 화살표 함수 문법을 이용했다.

💡
화살표 함수는 ES6 문법에서 함수를 표현하는 새로운 방법이며 function 이용한 함수 선언 방식을 아에 대체는 하지 않으며 사용 용도가 다르다. 주로 함수를 파라미터로 전달할 때 유용하고 값을 연산하여 바로 반환해야 할 때 사용하면 가독성을 높일 수 있다. 일반 함수는 자신의 종속된 객체를 this 가리키고 화살표 함수는 자신이 종속된 인스턴스를 가리킵니다.

 

모듈 내보내기 및 불러오기

 

모듈 내보내기 export

export default MyComponent;

이 코드를 선언 하면 이 파일을 import하면 위에서 선언한 MyComponent 클래스를 불러온다.

 

모듈 불러오기 import

import MyComponent from './MyComponent';

이 코드를 선언 하면 MyComponent 컴포넌트를 불러온다.

 

 

props

properties를 줄인 표현으로 컴포넌트 속성을 설정할 때 사용하는 요소입니다. props 값은 해당 컴포넌트를 불러와 사용하는 부모 컴포넌트에서 설정 할 수 있다.

import React from 'react';

const MyComponent = props => {
	return <div>hi {props.name} ~</div>;
}

 

import React from 'react';

const MyComponent = props => {
	return <div>hi {props.name} ~</div>;
}

다음과 같이 props를 이용 할 때도 JSX 문법 {}을 이용하여 처리하며 해당 컴포넌트를 불러올 때 props를 사용 했던 정보를 속성으로 담아서 보내준다.

 

props 기본값 설정: defaultProps

 

MyComponent.defaultProps = {
	name : '기본 이름'
}

export default MyComponent

기본 값으로 설정 하였을 시 속성으로 안 넣어도 default 값을 보여준다

 

태그 사이의 내용을 보여 주는 children

<MyComponent> react </MyComponent>

윗 처럼 태그 사이의 값을 넣을 시 {props.children} 을 이용하여 값을 보여준다.

 

props를 조금 더 편하게 쓰기

import React from 'react';
 
const MyComponent = props => {
  const { name, children } = props;
  return (
    <div>
      안녕하세요, {name}, {children}
    </div>
  );
};

이런 식으로 작성하면 props를 붙이지 않고 넣고싶은 구간에 편하게 작성 할 수 있다.

조금 더 간결하게 하면

import React from 'react';
 
const MyComponent = ({ name, children }) => {
  return (
    <div>
      안녕하세요, {name}, {children}
    </div>
  );
};

파라미터로 받아와서 비구조화 할당 문법을 사용 할 수 있다

 

props 검증 : propTypes

props의 타입을 지정할 때는 propTypes를 사용하여 지정한다.

MyComponent.propTypes = {
  name: PropTypes.string
};

 

isRequired를 사용하여 필수 propTypes 설정한다.

propTypes 지정하지 않았을 때 경고 띄워 주는 작업

MyComponent.propTypes = {
  name: PropTypes.string,
  favoriteNumber: PropTypes.number.isRequired
};

favoriteNumber가 설정을 하지 않을 시 경고가 나타남

 

더 많은 PropType 종류

  • array : 배열
  • arrayOf(다른 PropType): 특정 PropType으로 이루어진 배열을 의미합니다. ex) arrayOf(PropTypes.number)는 숫자로 이루어진 배열입니다
  • bool: true 혹은 false 값
  • func: 함수
  • number: 숫자
  • object: 객체
  • string: 문자열
  • symbol: ES6의 Symbol
  • node: 렌더링할 수 있는 모든 것(숫자, 문자열, 혹은 JSX 코드. children도 node PropType입니다.)
  • instanceOf(클래스): 특정 클래스의 인스턴스(예: instanceOf(MyClass))
  • oneOf(['dog', 'cat']): 주어진 배열 요소 중 값 하나
  • oneOfType([React.PropTypes.string, PropTypes.number]): 주어진 배열 안의 종류 중 하나
  • objectOf(React.PropTypes.number): 객체의 모든 키 값이 인자로 주어진 PropType인 객체
  • shape({ name: PropTypes.string, num: PropTypes.number }): 주어진 스키마를 가진 객체
  • any: 아무 종류

 

클래스형 컴포넌트에서 props

import React, { Component } from 'react';
import PropTypes from 'prop-types';
 
class MyComponent extends Component {
  render() {
    const { name, favoriteNumber, children } = this.props; // 비구조화 할당
    return (
    <div>
      안녕하세요, {name}, {children}, {favoriteNumber}
    </div>
    );
  }
}
 
MyComponent.defaultProps = {
  name: '기본 이름'
};
 
MyComponent.propTypes = {
  name: PropTypes.string,
  favoriteNumber: PropTypes.number.isRequired
};
 
export default MyComponent;

클래스형 컴포넌트에서 달라진 부분: this.props를 이용해서 데이터를 넣어주는 비구조화 할당

propType은 똑같이 사용할 수 있다.

 

하지만 class 내부에서 지정하는 다음과 같은 방법이 있다.

import React, { Component } from 'react';
import PropTypes from 'prop-types';
 
class MyComponent extends Component {
  static defaultProps = {
    name: '기본 이름'
  };
  static propTypes = {
    name: PropTypes.string,
    favoriteNumber: PropTypes.number.isRequired
  };
  render() {
	const { name, favoriteNumber, children } = this.props; // 비구조화 할당
	    return (...);
	  }
	}
	 
export default MyComponent;

static을 이용해서 propTypes, defaultProps를 정의한다.

 

💡
defaultProps와 propType을 사용이 꼭 필요하나 ? 굳이 필요는 없지만 대규모의 프로젝트를 진행하면 어떤 props가 필요한지 알 수 있어 개발 능률이 좋아질 것이다.

 

State

컴포넌트 내부에서 바뀔 수 있는 값을 의미한다.

props는 컴포넌트가 사용되는 과정에서 부모 컴포넌트가 설정하는 값이라 컴포넌트에서 자신은 해당 props를 읽기 전용으로만 사용할 수 있다. props를 바꾸려면 부모 컴포넌트에서 바꿔준다.

 

2가지의 state가 있다

  1. 클래스형 컴포넌트가 지니는 state
  1. 함수형 컴포넌트에서 사용하는 useState
constructor(props) {
    super(props);
    // state의 초깃값 설정하기
    this.state = {
      number: 0
    };
  }

해당 코드는 컴포넌트의 생성자 메서드이며 반드시 super(props) 를 호출해 주어야 합니다.

함수를 호출하면 현재 클래스형 컴포넌트가 상속받고 있는 리액트의 Component 클래스가 지닌 생성자 함수를 호출해 줍니다.

그다음 this.state 값에 초기 값을 설정

render() {
    const { number } = this.state; // state를 조회할 때는 this.state로 조회합니다.
    return (
      <div>
        <h1>{number}</h1>
				<button
          onClick={() => {
						 // onClick을 통해 버튼이 클릭되었을 때 호출할 함수를 지정합니다.
            // this.setState를 사용하여 state에 새로운 값을 넣을 수 있습니다.
            this.setState({ number: number + 1 });
          }}         
        >
          +1
        </button>
      </div>
    );
  }

render 함수에서 현재 state를 조회할 때는 this.state를 조회하면 된다. button안에 onclick안에 props로 넣어 주었는데 버튼이 클릭할 때 호출시킬 함수를 설정할 수 있게 해 준다.

setState를 사용하면 state값을 업데이트 하는데 상태가 비동기적으로 업데이트 됩니다.

 

onClick={() => {
  // this.setState를 사용하여 state에 새로운 값을 넣을 수 있습니다.
  this.setState({ number: number + 1 });
  this.setState({ number: this.state.number + 1 });
}

다음과 같은 코드가 있을 때 버튼을 클릭하면 2가 나와야 정상이지만 state는 값이 바로 바뀌지 않는다.

이를 해결 하기 위해 함수를 인자로 넣어 주는 방법을 이용

<button
  // onClick을 통해 버튼이 클릭되었을 때 호출할 함수를 지정합니다.
  onClick={() => {
    this.setState(prevState => {
      return {
        number: prevState.number + 1
      };
    });
    // 위 코드와 아래 코드는 완전히 똑같은 기능을 합니다.
    // 아래 코드는 함수에서 바로 객체를 반환한다는 의미입니다.
    this.setState(prevState => ({
      number: prevState.number + 1
    }));
	}}
>ss </button>

 

setState가 끝난 후 특정 작업을 원할 때

onClick={() => {
    this.setState(
      {
        number: number + 1
      },
      () => {
        console.log('방금 setState가 호출되었습니다.');
        console.log(this.state);
      }
    );
  }}

콜백 함수를 등록하면 state동작이 끝난 후 특정 작업을 실행 할 수 있다.

 

함수형 컴포넌트에서 State

원래 함수형 컴포넌트에서는 state를 사용할 수 없었다. 하지만 16.8 이후로 hooks라는 것을 사용하게 되어서 useState를 이용하여 state를 사용할 수 있게 되었다.

 

비구조화 할당

배열이나 객체의 속성 혹은 값을 해체하여 그 값을 변수에 각각 담아 사용하는 자바스크립트 표현식이다.

즉 배열 안에 들어 있는 값을 쉽게 추출할 수 있도록 해 주는 문법이다.

// 비구조화 할당 사용 전
const array = [1, 2];
const one = array[0];
const two = array[1];

// 비구조화 할당 사용 후 
const array = [1, 2];
const [one, two] = array;

useState 이용하기

import React, { useState } from 'react';
 
const Say = () => {
  const [message, setMessage] = useState('');
  const onClickEnter = () => setMessage('안녕하세요!');
  const onClickLeave = () => setMessage('안녕히 가세요!');
 
  return (
    <div>
      <button onClick={onClickEnter}>입장</button>
      <button onClick={onClickLeave}>퇴장</button>
      <h1>{message}</h1>
    </div>
  );
};
 
export default Say;

현제 useState를 반환된 message와 setMessage의 상태를 말하자면

message는 현재 상태 setMessage는 상태를 바꾸어 주는 함수이다.

 

💡
주의할 점은 message로 값을 변경시키면 안된다 message = "안녕하세요" (X) setMessage("안녕하세요") (O)

 

'Javascript > react' 카테고리의 다른 글

ref  (0) 2022.01.09
컴포넌트 반복  (0) 2022.01.09
이벤트 핸들링  (0) 2022.01.09
React 란 ?  (0) 2021.12.28