공부블로그

리액트 3장. 컴포넌트 본문

리액트/리액트를 다루는 기술

리액트 3장. 컴포넌트

떠어영 2021. 1. 4. 04:18

리액트를 사용하여 애플리케이션의 인터페이스를 설계할 때, 사용자가 볼 수 있는 요소는 여러가지 '컴포넌트'로 구성되어 있다. 

 

컴포넌트의 기능은 단순한 템플릿 이상이다.

데이터가 주어졌을 때 그에 맞추어 UI를 만들어 주기도 하고, 라이프사이클 API를 이용하여 컴포넌트가 화면에서 나타날 때, 사라질 때, 변화가 일어날 때 주어진 작업들을 처리할 수 있으며, 임의 메서드를 만들어 특별한 기능을 붙여줄 수도 있다. 

 

이번 장에서는 새로운 컴포넌트를 만들고 사용하는 방법,

컴포넌트의 속성 값을 지닌 props와 상태 값을 지닌 state를 사용하는 방법을 알아보자.

 

 

 

3. 1) 클래스형 컴포넌트 

 

- 2장에서 보았던 App컴포넌트는 함수형 컴포넌트이다.

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() { // render함수 필수!
    	const name = 'react';
        return <div className="react">{name}</div>; //보여주어야 할 JSX반환
    }
}

export default App;

우선 이 책에서는 함수형 컴포넌트를 활용하여 기본기를 익힌다.

 

 

 

3. 2) 첫 컴포넌트 생성

 

  1. 파일 만들기

  2. 코드 작성하기

  3. 모듈 내보내기 및 불러오기

src디렉터리에 MyComponent.js 파일을 생성해서 새 컴포넌트 코드를 작성해보자.

import React from "react";

const MyComponent = () => { //함수형 컴포넌트, ( ) => { } 를 사용해서 함수를 만듦.
  return <div>나의 새롭고 멋진 컴포넌트</div>;
};

export default MyComponent; //모듈 내보내기

 

(+) 여기서 화살표 함수는 ES6 문법에서 함수를 표현하는 새로운 방식이다.

 

functoin twice ( value ) {          

    return value * 2;                           =>              const twice = (value) => value  * 2;

  }                                                                      함수이름      인자          함수식

 

 

MyComponent컴포넌트를 만들었으니, App컴포넌트에서 불러와 사용해보자.

import React from "react";
import MyComponent from "./MyComponent"; // 컴포넌트 불러오기

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

export default App;

( 실행화면 )

3. 3) props: 컴포넌트 속성을 설정, 부모 컴포넌트 (현재는 App컴포넌트)에서 설정할 수 있다.

 

  1. MyComponent. js를 수정하여 name이라는 props을 랜더링하도록 작성해보자.

  ( 자식(?) 컴포넌트에서 props들을 선언하고 기본값, propTypes를 설정해주면 )

import React from "react";

const MyComponent = (props) => { //함수의 인자로 props를 받아와 사용
  return <div>안녕하세요, 제 이름은 {props.name}입니다.</div>; // {}로 감싸주기 
};

/*
  부모컴포넌트에서 name속성이 설정되지 않았을 경우.defaultProps를 사용하여 기본값을 설정할 수 있다. 
  MyComponent.defaultProps = {
  	name = 'default value'
    };
*/

export default MyComponent;

 

2. App. js에서 MyComponent의 props값을 설정.

  ( 부모 컴포넌트에서 props들을 설정 )

import React from "react";
import MyComponent from "./MyComponent"; // 컴포넌트 불러오기

const App = () => { 
  return <MyComponent name="React" />;   //name(이라는 props) = "React"라고 설정
};  

export default App;

(실행화면)

3. 3-1) 태그 사이의 내용을 보여주는 children

 

App. js

<MyComponent>리액트</MyComponent>

 

MyComponent. js 

return(<div> children 값은{props.children}</div>);
//App.js의 <MyComponent>태그 사이의 내용을 보여줌 

 

 

3. 3-2 ) 비구조화 할당 문법

 

MyComponent. js 

const MyComponent = (props) => {
  const { name, children } = props; //props라고 선언 (비구조화 할당 문법)
  //또는 파라미터부분에서({ name, children })
  return (
    <div>
      안녕하세요, 제 이름은 {name} 입니다. <br />
      children 값은 {children} 입니다.
    </div>
  );
};

 

 

3. 3-3 ) PropTypes

 

MyComponent. js

import PropTypes from "prop-types";
//필수 props를 지정하거나 props의 타입을 지정할 때 사용

...

MyComponent.propTypes = {
 	name: PropTypes.string, // name값은 무조건 string 형태
  	favoritenumber: PropTypes.number.isRequired,  
    // favoritenumber값은 무조건 숫자이고, isRequired이므로 필수props이다.
 
  // ex) App.js에서 name = {3}으로 작성하면 실행되기는 하지만 경고가 뜬다.
};

 

- 더 많은 propTypes의 종류로는 array, arrayOf (PropTypes.number), bool, func, object, node, instanceOf....등이 있다.

 

 

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

import React, { Component } from "react";
import PropTypes from "prop-types";
//필수 props를 지정하거나 props의 타입을 지정할 때 사용

class MyComponent extends Component {
  static defaultProps = {
    //class내부에서 defaultProps지정
    name: "defaultname",
  };
  static propTypes = {
    //class내부에서 propTypes지정
    name: PropTypes.string,
    favoritenumber: PropTypes.number.isRequired,
  };

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

export default MyComponent;

 

 

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

 

새로운 컴포넌트 Counter. js를 작성해보자.

import React, { Component } from "react";

class Counter extends Component {
  constructor(props) {
    //state를 설정하는 constructor 메서드
    super(props); //반드시 호출해야함
    //현재 컴포넌트가 상속받고 있는 리액트의 Component클래스가 지닌 생성자함수를 호출
    this.state = {
      number: 0, //state의 초기값 설정, state는 객체 형식!
    };
  }
  /* constructor없이 초기값 설정
  state = {
    username: "",
    message: "",
  };*/
  render() {
    const { number } = this.state; //state를 조회
    return (
      <div>
        <h1>{number}</h1>
        <button
          onClick={() => {
            //onClick 은 버튼의props
            //onClick을 통해 버튼이 클릭되었을 때 호출할 함수를 지정
            this.setState({ number: number + 1 });
            //setState를 사용해서 state에 새로운 값을 넣음
          }}
        >
          +1
        </button>
      </div>
    );
  }
}
export default Counter;

 

App. js

import React from "react";
import Counter from "./Counter"; // 컴포넌트 불러오기

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

export default App;

(실행화면)

3. 4. 1 ) this. setState에 객체 대신 함수 인자를 전달하는 경우 = 동기적으로 업데이트

 

(형식)

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

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

Counter. js - button

        <button
          onClick={() => {
            this.setState((prevState) => {
              //동기적으로 업데이트를 하고 싶으면 객체 대신 함수 인자를 전달!
              return {
                number: prevState.number + 1,
              };
            });
            
            this.setState((prevState) => ({
              number: prevState.number + 1,
            })); //함수에서 바로 객체를 반환
          }}
        >
          +1
        </button>
      </div>
    );
  }
}
export default Counter;

위와 같이 작성한 후 랜더링하면 버튼을 누를 때마다 숫자가 2씩 증가한다.

 

 

3. 4. 2 ) setState가 끝난 후 작업을 실행하고 싶을 때는 setState의 두번째 파라미터로 콜백함수를 등록하여 처리한다.

<button
          onClick={() => {
            this.setState(
              {
                number: number + 1,
              },
              () => { //setState의 두번째 파라미터로 콜백함수를 등록
                console.log("방금 setState가 호출되었습니다. ");
                console.log(this.state);
              }
            );
          }}
        >

 

 

3. 4. 3 ) 함수형 컴포넌트에서 useState 사용하기

 

새로운 컴포넌트 Say. js를 작성해보자.

import React, { useState } from "react";
//함수형 컴포넌트에서는 useState사용
const Say = () => {
  const [message, setMessage] = useState(""); //useState의 인자에는 상태의 초기값을 넣어줌
  //useState함수를 호출하면 배열이 반환
  //( 첫번째 원소는 현재상태->message, 두번째 원소는 상태를 바꿔주는 함수->setMessage)
  const onClickEnter = () => setMessage("안녕하세요");
  const onClickLeave = () => setMessage("안녕히 가세요");

  return (
    <div>
      <button onClick={onClickEnter}>입장</button>
      <button onClick={onClickLeave}>퇴장</button>
      <h1>{message}</h1>
    </div>
  );
};

export default Say;

 

useState는 여러번 사용할 수 있다.

 

 

이번 장에서는 컴포넌트를 내보내고 불어오는 방법과 props 및 state를 사용하는 방법에 대해 알아보았다.

props와 state는 모두 컴포넌트에서 사용하거나 랜더링할 데이터를 담고있지만,

props는 부모컴포넌트가 설정하고

state는 컴포넌트 자체적으로 지닌 값으로 컴포넌트 내부에서 값을 업데이트할 수 있다.

 

이후 만들어 볼 일정 관련 애플리케이션은 props을 유동적으로 사용하는 방식으로 설계하게 된다.