컴포넌트

정다윤·2023년 1월 27일
0

React

목록 보기
3/12
post-thumbnail

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

컴포넌트를 선언하는 방식은 두가지 입니다.
1. 함수 컴포넌트
2. 클래스형 컴포넌트

함수 컴포넌트는 코드가 다음과 같은 구조로 이루어져 있습니다.

import './App.css';

function App(){
	const name = '리액트';
    return <div className=:"react">{name}</div>;
}

export default App;

클래스형 컴포넌트는 코드가 다음과 같은 구조로 이루어져 있습니다.

import { Component } from 'react';

class App extends Component {
	render() {
    	const name = '리액트';
    	return <div className=:"react">{name}</div>;
    }
}

export default App;

클래스형 컴포넌트와 함수 컴포넌트의 차이점은 클래스형 컴포넌트의 경우 이후 배울 state 기능 및 라이프 사이클 기능을 사용할 수 있다는 것과 임의 메서드를 정의할 수 있다는 것입니다.
클래스형 컴포넌트에서는 render 함수가 꼭 있어야 하고, 그 안에서 보여줘야할 JSX를 반환해야합니다.

첫 컴포넌트 생성하기

  1. src 디렉터리에 MyComponent.js 파일 생성
  2. 함수 컴포넌트로 첫 컴포넌트 코드 작성
const MyConponent = () => {
	return <div><h1>나의 첫 컴포넌트</h1></div>;
};

export default MyComponent;
  1. 모듈 내보내기 및 불러오기
  • 모듈 내보내기(export)는 다른 파일에서 이 파일을 import 할 때, 위에서 선언한 MyCoponent 클래스를 불러오도록 설정합니다.
export default MyComponent;
  • 모듈 불러오기(import)는 컴포넌트를 불러옵니다.
import MyComponent from './MyComponent';

const App = () => {
	return <MyComponent />
};

export default App;

Props

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

JSX 내부에서 Props 렌더링

name이라는 props를 렌더링하도록 설정해봅시다. props 값은 컴포넌트 함수의 파라미터로 받아와서 사용할 수 있습니다.

const MyComponent = props => {
	return <div><h1>안녕하세요, 제 이름은 {props.name}입니다.</h1></div>;
}

export default MyComponent;

컴포넌트를 사용할 때 props 값 지정하기

import MyComponent from './MyComponent';

const App = () => {
	return <MyComponent name="React" />;
}

export default App;

props 기본값 설정 : defaultProps

const MyComponent = props => {
	return <div><h1>안녕하세요, 제 이름은 {props.name}입니다.</h1></div>;
}

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

export default MyComponent;

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

App.js

import MyComponent from "./MyComponent";

const App = () => {
  return <MyComponent>리액트</MyComponent>;
};

export default App;

MyComponent.js

const MyComponent = (props) => {
  return (
    <div>
      <h1>
        안녕하세요, 제 이름은 {props.name}입니다.
        <br />
        children 값은 {props.children} 입니다.
      </h1>
    </div>
  );
};

MyComponent.defaultProps = {
  name: "기본 이름",
};

export default MyComponent;

비구조화 할당 문법을 통해 props 내부 값 추출하기

MyComponent에서 props 값을 조회할 때마다 props.name, props.children과 같이 props 라는 키워드를 붙여주고 있습니다.
ES6의 비구조화 할당 문법을 사용하여 내부 값을 바로 추출하는 방법을 알아보겠습니다.

MyComponent.js

const MyComponent = (props) => {
  const { name, children } = props;
  return (
    <div>
      <h1>
        안녕하세요, 제 이름은 {name}입니다.
        <br />
        children 값은 {children} 입니다.
      </h1>
    </div>
  );
};

MyComponent.defaultProps = {
  name: "기본 이름",
};

export default MyComponent;

더 간단하게 줄이는 방법도 존재합니다.

MyComponent.js

const MyComponent = ({ name, children }) => {
  return (
    <div>
      <h1>
        안녕하세요, 제 이름은 {name}입니다.
        <br />
        children 값은 {children} 입니다.
      </h1>
    </div>
  );
};

MyComponent.defaultProps = {
  name: "기본 이름",
};

export default MyComponent;

propTypes를 통한 props 검증

컴포넌트 필수 props를 지정하거나 props 타입을 지정할 때는 propTypes를 사용합니다.

MyComponent.js

import PropTypes from "prop-types";

const MyComponent = ({ name, children }) => {
  return (
    <div>
      <h1>
        안녕하세요, 제 이름은 {name}입니다.
        <br />
        children 값은 {children} 입니다.
      </h1>
    </div>
  );
};

MyComponent.defaultProps = {
  name: "기본 이름",
};

MyComponent.protoTypes = {
  name: PropTypes.string,
};

export default MyComponent;

이렇게 설정해주면 name의 값은 무조건 문자열(string)형태로 전달해야 된다는 것을 의미합니다.

isRequired를 사용하여 필수 propTypes 설정

MyComponent.js

import PropTypes from "prop-types";

const MyComponent = ({ name, favoriteNumber, children }) => {
  return (
    <div>
      <h1>
        안녕하세요, 제 이름은 {name} 입니다.
        <br />
        children 값은 {children} 입니다.
        <br />
        제가 좋아하는 숫자는 {favoriteNumber} 입니다.
      </h1>
    </div>
  );
};

MyComponent.defaultProps = {
  name: "기본 이름",
};

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

export default MyComponent;

App.js

import MyComponent from "./MyComponent";

const App = () => {
  return (
    <MyComponent name="React" favoriteNumber={11}>
      리액트
    </MyComponent>
  );
};

export default App;

클래스형 컴포넌트에서 Props 사용하기

클래스형 컴포넌트에서 props를 사용할 때는 render 함수에서 this.props를 조회하면 됩니다.

MyComponent.js

import { Component } from "react";
import PropTypes from "prop-types";

class MyComponent extends Component {
  render() {
    const { name, favoriteNumber, children } = this.props; //비구조화 할당
    return (
      <div>
        <h1>
          안녕하세요, 제 이름은 {name} 입니다.
          <br />
          children 값은 {children} 입니다.
          <br />
          제가 좋아하는 숫자는 {favoriteNumber} 입니다.
        </h1>
      </div>
    );
  }
}

MyComponent.defaultProps = {
  name: "기본 이름",
};

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

export default MyComponent;

클래스형 컴포넌트에서 defaultProps와 propTypes를 설정할 때 Class 내부에서 지정하는 방법도 있습니다.

MyComponent.js

import { Component } from "react";
import PropTypes from "prop-types";

class MyComponent extends Component {
  static defaultProps = {
    name: "기본 이름s",
  };
  static propTypes = {
    name: PropTypes.string,
    favoriteNumber: PropTypes.number.isRequired,
  };
  render() {
    const { name, favoriteNumber, children } = this.props; //비구조화 할당
    return (
      <div>
        <h1>
          안녕하세요, 제 이름은 {name} 입니다.
          <br />
          children 값은 {children} 입니다.
          <br />
          제가 좋아하는 숫자는 {favoriteNumber} 입니다.
        </h1>
      </div>
    );
  }
}

export default MyComponent;

state

state는 컴포넌트 내부에서 바뀔 수 있는 값을 의미합니다.
props는 컴포넌트가 사용되는 과정에서 부모 컴포넌트가 설정하는 값이며, 컴포넌트 자신은 해당 props를 읽기 전용으로만 사용할 수 있습니다.

클래스형 컴포넌트의 state

클래스형 컴포넌트의 state를 이해하기 위해 src/Counter.js 파일을 생성합니다.

Counter.js

import { Component } from "react";

class Counter extends Component {
  constructor(props) {
    super(props);
    //state의 초깃값 설정하기
    this.state = {
      number: 0,
    };
  }
  render() {
    const { number } = this.state; //state를 조회할 때는 this.state로 조회합니다.
    return (
      <div>
        <h1>{number}</h1>
        <button
          //on Click을 통해 버튼이 클릭되었을 때 호출할 함수를 지정합니다.
          onClick={() => {
            //this.setState 를 사용하여 state에 새로운 값을 넣을 수 있습니다.
            this.setState({ number: number + 1 });
          }}
        >
          +1
        </button>
      </div>
    );
  }
}

export default Counter;

컴포넌트에 state를 설정할 때는 위와 같이 constructor 메서드(컴포넌트의 생성자 메서드)를 작성하여 설정합니다. 클래스형 컴포넌트에서 constructor를 작성할 때는 반드시 super(props)를 호출해줘야 합니다. 이 함수가 호출되면 현재 클래스형 컴포넌트가 상속받고 있는 리액트의 Component 클래스가 지닌 생성자 함수를 호출해줍니다.

App.js

import Counter from "./Counter";

const App = () => {
  return <Counter />;
};

export default App;

state 객체 안에 여러 값이 있을 때

Counter.js

import { Component } from "react";

class Counter extends Component {
  constructor(props) {
    super(props);
    //state의 초깃값 설정하기
    this.state = {
      number: 0,
      fixedNumber: 0,
    };
  }
  render() {
    const { number, fixedNumber } = this.state; //state를 조회할 때는 this.state로 조회합니다.
    return (
      <div>
        <h1>{number}</h1>
        <h1>바뀌지 않는 값 : {fixedNumber}</h1>
        <button
          //on Click을 통해 버튼이 클릭되었을 때 호출할 함수를 지정합니다.
          onClick={() => {
            //this.setState 를 사용하여 state에 새로운 값을 넣을 수 있습니다.
            this.setState({ number: number + 1 });
          }}
        >
          +1
        </button>
      </div>
    );
  }
}

export default Counter;

state를 constructor에서 꺼내기

Counter.js

import { Component } from "react";

class Counter extends Component {
  state = {
    number: 0,
    fixedNumber: 0,
  };
  render() {
    const { number, fixedNumber } = this.state; //state를 조회할 때는 this.state로 조회합니다.
    return (...);
  }
}

export default Counter;

this.setState에 객체 대신 함수 인자 전달하기

this.setState를 사용하여 state값을 업데이트할 때는 상태가 비동기적으로 업데이트 됩니다. 이에 대한 해결책은 this.setState를 사용할 떄 객체 대신 함수를 인자로 넣어주는 것입니다.

this.setState((prevState, props) =>{
	return{
    	//업데이트하고 싶은 내용
    }
})

this.setState가 끝난 후 특정 작업 실행하기

setState를 사용하여 값을 업데이트하고 난 다음에 특정 작업을 하고 싶을떄는 setState의 두번째 파라미터로 콜백 함수를 등록하여 작업을 처리할 수 있습니다.

함수 컴포넌트에서 useState 사용하기

  • 배열 비구조화 할당
const array = [1,2];              =>          const array = [1,2];
const one = array[0];                         const [one,two] = array;
const two = array[1];

useState 사용하기

Say.js

import { 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 여러번 사용하기

Say.js

import { useState } from 'react';

const Say = () => {
  const [message, setMessage] = useState('');
  const onClickEnter = () => setMessage('안녕하세요!');
  const onClickLeave = () => setMessage('안녕히 가세요!');

  const [color, setColor] = useState('black');

  return (
    <div>
      <button onClick={onClickEnter}>압장</button>
      <button onClick={onClickLeave}>퇴장</button>
      <h1 style={{ color }}>{message}</h1>
      <button style={{ color: 'red' }} onClick={() => setColor('red')}>
        빨간색
      </button>
      <button style={{ color: 'green' }} onClick={() => setColor('green')}>
        초록색
      </button>
      <button style={{ color: 'blue' }} onClick={() => setColor('blue')}>
        파란색
      </button>
    </div>
  );
};

export default Say;

props와 state 는 둘 다 컴포넌트에서 사용하거나 렌더링할 데이터를 담고 있으므로 비슷해보일 수 있지만 역할은 매우 다릅니다.

  • props는 부모컴포넌트가 설정
  • state는 컴포넌트 자체적으로 지닌 값으로 컴포넌트 내부에서 값을 업데이트할 수 있습니다.

리액트를 다루는 기술 [개정판] (김민준, 길벗출판사) 책을 참고하였습니다.

0개의 댓글