카테고리 없음

React 컴포넌트

ㅈ현 2022. 7. 2. 15:42

React 컴포넌트는 크게 함수형 컴포넌트와 클래스형 컴포넌트로 나뉜다.

클래스형 컴포넌트는 함수형 컴포넌트의 기능 + state기능, 라이프 사이클 기능이 추가된 것이다.

 

React에서는 클래스형 컴포넌트 개발 방식에 대해 지원하겠다 하지만, 새로 개발되는 컴포넌트의 경우에는 함수형 컴포넌트를 우선적으로 할것을 권장한다. 굳이 클래스형 컴포넌트를 함수형 컴포넌트로 바꿀 필요는 없지만 함수형 컴포넌트로 개발을 우선적으로 생각해볼 필요는 있다.

 

해당 포스팅에서는 컴포넌트의 대략적인 기능을 함수형 컴포넌트로 설명하고, 클래스형 컴포넌트에서는 어떻게 사용하는지에 대해 설명한다.

 

첫번째 컴포넌트

firstComponent.js

import React from 'react';
const MyComponent = () => {
    return <div>나의 첫번째 컴포넌트</div>;
}
export default MyComponent;


App.js

import React, {Component} from 'react';
import MyComponent from './firstComponent';

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


함수형 컴포넌트인 MyComponent를 사용하는 예제다.


props

props는 properties를 줄인것으로 컴포넌트 속성을 설정할때 사용하는 요소임.  
부모 => 자식 컴포넌트로 값을 전달할때 사용한다


1. 자식 컴포넌트에서 props를 파라미터로 받아서 사용

child.js

const MyComponent = (props) => {
    return <div>나의 첫번째 컴포넌트 {props.name} </div>;
}

 

2. 부모 컴포넌트에서 자식 컴포넌트를 사용할때 attirube를 넣어줘 props값을 지정함.

parents.js

...
<MyComponent name = "jh kim"/>
...


default props

디폴트값 지정

컴포넌트를 작성한 파일에서
{Component}.defaultProps를 통해 컴포넌트의 default props값을 지정한다.


firstComponent.js

MyComponent.defaultProps = {
    name: "jhkim"
}



children


태그 사이의 내용을 보여준다.
부모 컴포넌트에서 자식 컴포넌트를 사용할때 태그 사이에 넣은 children값이다.  

props.children 을 통해 사용함

 


children.js

const MyComponent = (props) => {
    return <div>나의 첫번째 컴포넌트 {props.children}</div>;
}

parents.js

<MyComponent name = "jh kim"> children 입니다.</MyComponent>


비구조화 할당


props로 넘어온 값을 조회할 때 마다 props.some, props.children으로 조회해야한다.  
이를 편하게 하고자 하기위해 아래와 같이 비구조화 할당을 해서 사용한다.

const {name, children} = props;

 

child.js

const MyComponent = (props) => {
    const {name, children} = props;
    return <div>나의 첫번째 컴포넌트 {name} {children}</div>;
}

// =========================동일한 방법

const MyComponent = ({name, children}) => {
    return <div>나의 첫번째 컴포넌트 {name} {children}</div>;
}

props로 넘어온 name, children 값을 위와같은 비 구조화 할당을 통해 사용한다.

단 이때 할당받을 변수의 필드는 동일해야 한다..


props.name과 props.children 을 받으려면  child 컴포넌트에서 변수명을 {name, children}으로 사용해야 하고,  {n, child}과 같이 다른 변수명으로 할당받으면 받지 못한다.



propTypes 자료형 지정


props로 넘어오는 자료형 및 필수 여부를 을 지정해줄 수 있다.

child.js

MyComponent.defaultProps = {
    name: PropTypes.string
    num: PropTypes.number.isRequired
}
//props.name은무조건 문자열로 전달되어야 한다.
//props.num은 무조건 숫자로 전달되어야 하며 반드시 전달되어야 한다.

 

PropTypes

  • array: 배열
  • arrayOf(PropType): 특정 PropType로 이루어진 배열
  • bool: true / false
  • func: 함수
  • number: 숫자
  • object: 객체
  • string: 문자열
  • symbol: ES6 심볼
  • node: 랜더링 가능한 모든 것
  • instanceOf(클래스): 특정 클래스 인스턴스
  • oneOf([a,b,c]): a,b,c로 주어진 배열 요소중 하나
  • oneOfType([a,b,c]): 배열 타입중 하나
  • any: 아무거나

 

state

state는 컴포넌트 내부에서 바뀔 수 있는 값을 의미한다.  
props는 부모 컴포넌트가 설정하는 값이며, 자신은 해당 props를 RO로만 사용할 수 있다.  
props를 바꾸려면 부모에서 바꿔줘야 함.  

 

함수형 컴포넌트 state 


함수형 컴포넌트에서는 state가 사용 불가하지만 16.8 버전 이후 useState를 사용하여 함수형 컴포넌트에서도 state가 사용 가능해짐.  
이때 Hooks라는것을 사용하게 된다. 

useState를 사용하기 위해선 import를 해야한다.

import

import React, {useState} from "react";
const Say = () => {
    const [msg, setMessage] = useState('init message');         
    // useState의 함수 리턴으로 [현재 상태, 상태 바꿔주는 함수]를 리턴함
    const onClickEnter = () => setMessage("hi");                
    // msg 상태를 "hi"로 바꿔주는 함수
    const onClickLeave = () => setMessage("Bye");               
    // msg 상태를 "Bye"로 바꿔주는 함수

    return (
        <div>
            <button onClick = {onClickEnter}>입장</button>      // onClickEnter를 실행해 msg 상태를 hi로 바꿈
            <button onClick = {onClickLeave}>퇴장</button>      // onClickLeave를 실행해 msg 상태를 Bye로 바꿈
            <h1>{msg}</h1>
        </div>
    )
}


# state 주의사항
state값을 바꿀때는 함수형, 클래스형 상관없이 setState, useState로 전달받은 setter함수를 사용해야 한다.  

const [name, setName] = useState('')
name = "jhkim"
setName("jhkim")

2행과 같이 state값에 직접 반영하지 않고, 무조건 setter함수를 통해 적용시켜야한다.

배열, 객체 업데이트 시에는 배열, 객체의 사본을 만들어 업데이트 후 setState, setter함수를 통해 업데이트 하는 방식으로 한다.  

 

클래스형 컴포넌트에서 state와 props 사용

Counter.js

class Counter extends Component {
    constructor(props){
        super(props);
        this.state = {
            number: 0
        };
    }
    //클래스형 컴포넌트에서 constructor를 작성할때는
    // 반드시 super(props)를 호출하여 상속하는 Component의 생성자 함수를 호출해 줘야함.
    // 컴포넌트의 state는 객체 형식이여야 함.

    render() {
        const {number} = this.state;        
        // 컴포넌트의 state 는 this.state로 조회, 비구조화 할당
        return (
            <div>
                <h1>{number}</h1>           
                <button
                    onClick={() => {    // 버튼 클릭시 호출할 함수
                        this.setState({ number: number + 1});
                    }}
                >+1</button>
                
                <button
                    onClick={() => {    // 버튼 클릭시 호출할 함수
                        this.setState({ number: number - 1});
                    }}
                >-1</button>
            </div>
        )
    }
}


또한 constructor를 사용하지 않고 state를 지정해 줄 수 있다.

class Counter extends Component {    
    // constructor(props){
    //     super(props);
    //     this.state = {
    //         number: 0
    //     };
    // }
    state = {
        number: 0
    };
    ...
    // 나머지 사용 방법은 동일.
}



this.setState

 

setState를 통해 state값을 비동기적으로 업데이트 할 수 있다.  

Counter1.js

onClick={() => {    // 버튼 클릭시 호출할 함수
    this.setState({ number: number - 1});
    this.setState({ number: number - 1});
}}



위와같이 사용하면, setState를 두번 사용함에도 불구하고, number는 -1만 된다.  
이는 바로 state값이 업데이트 되는것이 아닌, 비동기적으로 동작하기 때문.  

Counter2.js

onClick={() => {
    this.setState((prevState) => {      // #1여기와
        return {
            number: prevState.number - 1
        }
    });
    this.setState((ps) => ({ number: ps.number - 1}));      //#2여기는 같은 동작임.
}}



위와같이 setState의 파라미터로 State값을 받아올 수 있다. 이렇게 받아온 previous state값에 연산 후  return을 하게 되면 Counter1.js 예제와 다르게 두번 -1이 적용되게 된다.


this.setState 콜백함수

 

Counter.js

this.setState((ps) => ({ 
    number: ps.number - 1
    })
, () => console.log(this.state));

 


export, import

만든 모듈은 export를 해야 사용이 가능해진다.
export에는 다음과 같은 방법이 있다.  
1. 마지막에 `export {name}`  하는 방법
    이때 import 할려면 import {name} from '' 으로 export, import 둘 다 중괄호를 쳐줘야 함.
2. 변수 앞에 export
    이때도 import 할려면 중괄호가 필요하다.
3. default 키워드를 붙여서 내보낸다.
    이떄는 내보낼때, import 할 때 중괄호 없이 식별이 가능하다.
    한 파일에서 export default는 **오직 하나만** 존재한다.