Develop/React.js

[React]Component

dawonny 2021. 7. 17. 02:41
728x90
반응형

이 글은 [리액트를 다루는 기술](저자 김민준, 출판사 길벗) 교재를 보고 공부하며 정리한 글임.


전에 보았던 App 컴포넌트는 함수형 컴포넌트

컴포넌트를 선언하는 방식은 두가지

함수형 컴포넌트와

클래스 컴포넌트

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

임의 메서드를 정의할 수 있다는 것

클래스형 컴포넌트에서는 render 함수가 꼭 있어야 하고 그 안에서 보여줄 JSX 를 반환해야함

하지만 함수형 컴포넌트의 단점은 Hooks라는 기능이 도입되면서 해결되었음

이젠 함수형 컴포넌트와 Hooks를 사용하도록 권장함


첫 컴포넌트 생성

src에 MyComponent라는 js 파일 만들어 주고

import React from 'react';

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

function 키워드 사용 대신에 () => {} 를 사용하여 함수를 만들어 주었다.

ES6의 화살표 함수 문법

일반함수는 자신이 종속된 객체를 this로 가리키고

화살표 함수는 자신이 종속된 인스턴스를 가리킨다(90페이지)


export default MyComponent;

라는 이 코드는 다른 파일에서 이 파일을 import 할때 위에서 선언한 MyComponent 클래스를 불러오도록 설정


MyComponent.js

import React from 'react';

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

App.js

import React from 'react';
import MyComponent from './MyComponent';

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

export default App;

브라우저에서 렌더링 되었는지 확인


props 값을 지정해보기

App.js

import React from 'react';
import MyComponent from './MyComponent';

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

export default App;

props의 기본값 defaultProps

name 값을 지우고 저장하면 브라우저에는 이름이 비어보일 것이다.

따로 props의 값을 지정하지 않았을때 보여주는 기본값

App.js

import React from 'react';
import MyComponent from './MyComponent';

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

export default App;

MyComponent.js

import React from 'react';

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

MyComponent.defaultProps ={
    name : '비어있는 이름'
};

export default MyComponent;

결과 화면


컴포넌트 태그 사이의 내용을 보여주는 children

App.js

import React from 'react';
import MyComponent from './MyComponent';

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

export default App;

MyComponent.js

import React from 'react';

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

};

MyComponent.defaultProps ={
    name : '비어있는 이름'
};

export default MyComponent;

결과화면

음 그러니까 App.js에서 MyComponent 태그 사이에 쓴 문자열을

MyComponent 안에서 출력하려면 props.children 으로 보여줘야한다는거지?


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

MyComponent에서 props값을 조회할때 더 편하게 하려고

ES6의 비구조화 할당 문법을 사용하기

MyComponent.js

import React from 'react';

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

};

MyComponent.defaultProps ={
    name : '비어있는 이름'
};

export default MyComponent;

이 문법은 구조 분해 문법이라고도 불림

함수 파라미터 부분에서도 사용가능함

MyComponent.js

import React from 'react';

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

};

MyComponent.defaultProps ={
    name : '비어있는 이름'
};

export default MyComponent;

이렇게 쓰면 더 편하다는 의미


propTypes 를 통한 props 검증

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

MyComponent.js

import React from 'react';
import PropTypes from 'prop-types';

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

};

MyComponent.defaultProps ={
    name : '비어있는 이름'
};

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

export default MyComponent;

이러면 name 은 모조건 string 형태여야 한다는 의미

string 이 아니어도 값이 나타나기는 하지만 콘솔에 경고 메세지가 출력됨


propTypes 를 지정 안했을 때 경고 메세지를 띄워주는 작업해보기

MyComponent.js

import React from 'react';
import PropTypes from 'prop-types';

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

};

MyComponent.defaultProps ={
    name : '비어있는 이름'
};

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

export default MyComponent;

App.js

import React from 'react';
import MyComponent from './MyComponent';

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

export default App;

클래스형 컴포넌트에서 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}입니다.<br />
            children 값은 {children}
            입니다.
            <br />
            제가 좋아하는 숫자는 {favoriteNumber}입니다.
        </div>
    );
    }
}

MyComponent.defaultProps ={
    name : '비어있는 이름'
};

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

export default MyComponent;

state

App.js

import React from 'react';
import Counter from './Counter';

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


export default App;

Counter.js

import React, {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
                //onClick을 통해 클릭되었을 때 호출할 함수 지정
                onClick={()=>{
                    //this.setState로 state에 새로운 값 넣기
                    this.setState({number:number+1});
                }}
                
        >
            +1
            </button>
            </div>
        );
    }
}

export default Counter;

state안에 여러 값이 있을 수 있다

Counter.js

import React, {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>
                <h2>바뀌지 않는 값:{fixedNumber}</h2>
                <button
                //onClick을 통해 클릭되었을 때 호출할 함수 지정
                onClick={()=>{
                    //this.setState로 state에 새로운 값 넣기
                    this.setState({number:number+1});
                }}
                
        >
            +1
            </button>
            </div>
        );
    }
}

export default Counter;

App.js

import React from 'react';
import Counter from './Counter';

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


export default App;


state 초기값 설정 constructor 메서드 선언하지 않고 하기

Counter.js

import React, {Component}from 'react';

class Counter extends Component{
    //여기서
    state = {
        number:0,
        fixedNumber:0
    };
    //여기까지
    render(){
        const{number,fixedNumber}=this.state;//state조회할때에는 this.state로 조회
        return(
            <div>
                <h1>{number}</h1>
                <h2>바뀌지 않는 값:{fixedNumber}</h2>
                <button
                //onClick을 통해 클릭되었을 때 호출할 함수 지정
                onClick={()=>{
                    //this.setState로 state에 새로운 값 넣기
                    this.setState({number:number+1});
                }}
                
        >
            +1
            </button>
            </div>
        );
    }
}

export default Counter;

this.setState에 객체말고 함수인자 전달

Counter.js

import React, {Component}from 'react';

class Counter extends Component{
    //여기서
    state = {
        number:0,
        fixedNumber:0
    };
    //여기까지
    render(){
        const{number,fixedNumber}=this.state;//state조회할때에는 this.state로 조회
        return(
            <div>
                <h1>{number}</h1>
                <h2>바뀌지 않는 값:{fixedNumber}</h2>
                <button
                //onClick을 통해 클릭되었을 때 호출할 함수 지정
                onClick={()=>{
                    //this.setState로 state에 새로운 값 넣기
                    this.setState(prevState=>{
                        return{
                            number:prevState.number+1
                        };
                });
//위 코드랑 아래 코드는 같은 기능

                //함수에서 바로 객체를 반환
                this.setState(prevState=>({
                    number:prevState.number +1
                }));
            }}
        >
            +1
            </button>
            </div>
        );
    }
}

export default Counter;

App.js

import React from 'react';
import Counter from './Counter';

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


export default App;

버튼 한번 누르면 2씩 증가함


this.setState 끝나고 특정 작업 하기

Counter.js

import React, {Component}from 'react';

class Counter extends Component{
    //여기서
    state = {
        number:0,
        fixedNumber:0
    };
    //여기까지
    render(){
        const{number,fixedNumber}=this.state;//state조회할때에는 this.state로 조회
        return(
            <div>
                <h1>{number}</h1>
                <h2>바뀌지 않는 값:{fixedNumber}</h2>
                <button
                //onClick을 통해 클릭되었을 때 호출할 함수 지정
                onClick={()=>{
                    //this.setState로 state에 새로운 값 넣기
                    this.setState(
                        {
                       number : number + 1
                        },
                        () => {
                            console.log('방금 setState 호출됨');
                            console.log(this.state);
                        }
                    );
                }}
                >

                
            +1
            </button>
            </div>
        );
    }
}

export default Counter;

누를때마다 바뀌는 거 볼 수 있음 ​


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

Say.js

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;

App.js

import React from 'react';
import Say from './Say';

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


export default App;

한 컴포넌트에서 useState 여러번 사용

import React, {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;

state 만들때 배열이나 객체를 업데이트 하려면

배열이나 객체 사본을 만들고

그 사본에 값을 업데이트하고

그 사본의 상태를 setState 혹은 세터 함수를 통해 업데이트 하기

뒤에 더 자세히 나옴

728x90
반응형