React(생활코딩)_12일차_함수형, 클래스형의 props & state 사용

Lina Hongbi Ko·2023년 9월 8일
0

React_생활코딩

목록 보기
13/23

저번 시간에는 리액트 라이브러리에 대한 정보들과 컴포넌트의 함수형 스타일과 클래스형 스타일을 잠깐 발 담궈 봤다.

오늘은 이 두 스타일의 state 사용법에 대해서 알아보자 :)

1. Props 사용

전에 실습했던 내용을 이용해서 함수형, 클래스형 컴포넌트에 props를 사용해보자.

// App.js 파일

... 생략 ...
function App() {
	return(
    	<div className="container">
        	<h1>Hello World</h1>
            <FuncComp initNumber={2}></FuncComp>
            <ClassComp initNumber={2}></ClassComp>
        </div>
    );
}
... 생략 ...

상위 컴포넌트는 props를 사용해 하위 컴포넌트에 명령할 수 있고, 하위 컴포넌트가 상위 컴포넌트에 지시를 하고 싶을때는 이벤트를 사용해서 state의 값을 바꿔주는 실습을 이제까지 해왔다.

먼저, 클래스방식인 ClassComp 컴포넌트는 props를 어떻게 받을까?

// App.js 파일

... 생략 ...

class ClassComp extends React.Component {
	render(){
    	return(
        	<div className="container">
            	<h2>class style component</h2>
                <p>Number: {this.props.initNumber}</p>
            </div>
        );
    }
}
... 생략 ...

위와 같이 외부에서 전달된 props값을 this.props.initNumber 같은 방식으로 받아 사용하는 것을 알 수 있다. this를 사용해 props의 initNumber를 받았다.

그렇다면 함수방식인 FuncComp 컴포넌트는 props를 어떻게 받을까?

// App.js 파일

... 생략 ...

function FuncComp(props) {
	return(
    	<div className="container">
        	<h2>function style component</h2>
            <p>Number: {props.initNumber}</p>
        </div>
    );
}

... 생략 ...

함수방식에서 props를 받을때는 this를 사용하지 않는다. 그리고 함수의 인자로 props가 추가 되었고, 값을 사용할때는 props.initNumber와 같이 값을 참조할 수 있다.

컴포넌트 함수를 리액트가 호출할때 첫번째 파라미터의 인자값으로 props값을 전달하도록 약속되어 있다고 한다.
따라서, 함수의 인자를 추가하고 그 인자를 사용해서 외부에서 전달된 initNumber값을 사용한 것을 알 수 있다.

이 때 주의할 점은, 함수의 인자로 전달된 props라는 값의 이름은 아무런 이름으로 정해도 상관없다. 단지 변수의 이름일 뿐이다.

자, 이렇게 함수형 컴포넌트와 클래스형 컴포넌트를 가지고 props를 어떻게 사용하는지 알아보았다.

다음은 state를 어떻게 사용하는지 알아보자.

2. state 사용

컴포넌트가 내부적으로 자신의 상태를 바꾸고 관리하는데 사용하는 state는 클래스형 컴포넌트에서는 어떻게 사용하고, 함수형 컴포넌트에서는 어떻게 사용하는지 알아보자~

먼저, 클래스형 컴포넌트를 보자.

// App.js 파일

... 생략 ...

class ClassComp extends React.Component {
	state = {
    	number: this.props.initNumber
    }
    render(){
    	return(
        	<div className="container">
            	<h2>class style component</h2>
                <p>Number: {this.state.number}</p>
            </div>
        );
    }
}
... 생략 ...

state의 초깃값을 props로 전달된 initNumber값으로 지정했다. 컴포넌트의 props에 initNumber값을 전달하면 컴포넌트 안에서 state의 number값이 2로 초기화되고 이 값을 사용할때는 this.state.number로 접근해 사용할 수 있다.

state값이 지정됐기 때문에 이 state 값을 바꿀때마다 render메서드가 호출되면서 새로 달라진 state의 number값이 UI에 바로 반영된다.

반영되는 것을 구현해보기 위해서 임의의 값이 발생하는 버튼을 만들어서 실습해보자.

// App.js 파일

... 생략 ...

class ClassComp extends React.Component {
	state = {
    	number: this.props.initNumber
    }
    render(){
    	return(
        	<div className="container">
            	<h2>class style component</h2>
                <p>Number: {this.state.number}</p>
                <input type="button" value="random" onClick={function(){
                	this.setState({number:Math.random()});
                }.bind(this)}></input>
            </div>
        );
    }
}
... 생략 ...

임의의 값을 발생시키는 버튼을 만들었다. onClick에는 임의의 값을 생성하고 이 값을 state의 number에 할당하는 기능을 작성했다. 버튼을 누르면 임의로 생성된 값으로 바뀌는 것을 볼 수 있다.

버튼을 누르면 state 값이 바뀌고, 값이 바뀌면 클래스 컴포넌트의 render 메서드가 호출되면서 바뀐 결과가 반영된다.

이렇게 클래스 컴포넌트에서 state를 설정하고 초기화하고 그 state에 값을 사용하고 변경하는 작업을 예전에는 함수형 컴포넌트에서 할 수 없었다. 이전에는 단지 props로 전달된 값을 화면에 표시하는 간단한 용도로만 함수형 컴포넌트를 사용했지만 이제는 '훅(hook)'을 통해서 state를 사용할 수 있게 되었다.

📍 함수방식에서 state 사용법 - hook(훅)

: 리액트에는 기본적으로 제공하는 내장된 훅이 있고, 사용자의 훅을 만들어서 사용할 수 있다.

훅의 특징은 이름이 'use'로 시작한다는 점이다.

💡 리액트에서 제공하는 훅의 이름은 useState 이다. 💡

이 훅은 내장된 훅이다.

그러면 이 훅을 이용해서 state를 사용해보자.

먼저, 리액트의 useState라는 함수를 호출한다. 코드를 작성해보자.

// App. js 파일

import React, { useState } from 'react';
import './App.css';

... 생략 ...

function FuncComp(props) {
	const numberState = useState(props.initNumber);
    const number = numberState[0];
    const setNumber = numberState[1];
    console.log('numberState', numberState);
    return(
    	<div className="container>
        	<h2>function style component</h2>
            <p>Number : {number}</p>
            <input type="button" value="random" onClick={function(){
            	setNumber(Math.random());
            }}></input>
        </div>
    );
}
... 생략 ...

코드 상단에서 일단 useState 함수를 import했다. 그리고 numberState 변수에 useState 함수의 반환값을 저장해 출력했다. 또한 numberState의 첫번째 요소의 값을 number 변수에 넣었고, numberState의 두번째 요소 값을 setNumber 변수에 넣고, 함수로 호출하도록 구현하고 있다.

실행 결과를 보면, console탭에서 useState의 반환값을 볼 수 있다. 반환값이 배열인것을 확인할 수 있는데, 그 중에서 첫번째 값은 우리가 원하는 state값이다.

클래스방식에서 state값을 지정할때는 this.props객체를 사용해 state에 값을 저장했지만,

함수방식에서 state의 초깃값을 지정할때는 useState함수의 첫 번째 인자로 값을 전달한다. 현재는 props의 initNumber 값이 2이기 때문에 console창에도 2가 출력되는 것을 알 수 있다.

클래스 컴포넌트에서는 random 버튼을 눌렀을때 값이 바뀌는 기능은 setState 함수를 이용했다.

함수 컴포넌트는 numberState(useState함수의 반환값)의 두번째 요소 값이 바로 상태를 바꾸는 함수이다. 이 함수의 인자에 우리가 원하는 새로운 state값을 전달하면 된다.

다시 말해, 함수형 컴포넌트에서 state를 만들때는 useState함수를 호출해야한다. 그리고 이 함수의 인자로 원하는 stae의 초깃값을 지정하면 된다. 그리고 앞의 예제에서 useState의 반환값은 길이가 2인 배열인 것을 알 수 있었다. 그리고 이 배열의 첫번째 요소의 값이 state이고, 두번째 요소의 값은 이 state값을 변경할 수 있는 함수이다.


자, 그럼 현재시각을 출력하고 버튼을 클릭하면 출력된 값이 현재 시각 값으로 업데이트 되는 코드를 작성해보자.

// App.js 파일

import React, { useState } from 'react';
import './App.css';

function App() {
	return(
    	<div className="container">
        	<h1>Hello World</h1>
            <FuncComp initNumber={2}></FuncComp>
            <ClassComp initNumber={2}></ClassComp>
        </div>
    );
}

function FuncComp(props) {
	const numberState = useState(props.initNumber);
    const number = numberState[0];
    const setNumber = numberState[1];
    
    const dateState = useState((new Date.()).toString());
    const _date = dateState[0];
    const setDate = dateState[1];
    console.log("numberState", numberState);
    
	return(
    	<div className="container">
        	<h2>function style component</h2>
            <p>Number : {number}</p>
            <p>Date : {_date}</p>
            <input type="button" value="random" onClick={function(){
            	setNumber(Math.random());
            }}></input>
            <input type="button" value="date" onClick={function(){
            	setDate((new Date.()).toString);
            }}></input>
        </div>
    );
}

function ClassComp(){
	state = {
    	number: this.props.initNumber,
        date:(new Date()).toString()
    }
    render(){
    	return(
        	<div className="container">
            	<h2>class style component</h2>
                <p>Number:{this.state.number}</p>
                <p>Date: {this.state.date}</p>
                <input type="button" value="random" onClick={function(){
                	this.setState({number: Math.random()});
                }.bind(this)}></iput>
                <input type="button" value="date" onclick={function(){
                	this.setState({date:(new Date()).toString()});
                }.bind(this)}></input>
            </div>
        );
    }
}

export default App;

클래스 컴포넌트에서는 state라는 하나의 객체 안에 number와 date를 모두 넣었지만 함수형 컴포넌트에서는 useState를 한 번 더 호출해서 state를 여러개 생성하는 방식으로 구현하였다.

책에서 useState를 사용해 state를 생성할때 코드를 좀 더 단순하고 보기 쉽게 구현하는 방법을 알려주었다.
아래의 코드를 보자.

// App.js 파일

... 생략 ...
function FuncComp(props) {
	const numberState = useState(props.initNumber);
    const number = numberState[0];
    const setNumber = numberState[1];
    
    // const dateState = useState((new Date()).toString());
    // const _date = dateState[0];
    // const setDate = dateState[1];
    
    const [_date, setDate] = useState((new Date()).toString());
    console.log('numberState', numberState);
    return(
    ... 생략 ...

앞의 세줄을 주석처리하고 한 줄로 쓴 코드를 보면,

const [_date, setDate] = useState((new Date()).toString());

변수를 선언할 때 배열을 나타내는 기호 []안에 변수 이름을 넣고, useState를 호출하면 useState 배열의 각 요소의 값이 _date, setDate 변수에 할당된다. state값은 자동적으로 _date가 될것이고 setDate를 이용해 state값을 바꿀 수 있다.

그렇다면 number도 적용해보자.

const [number, setNumber] = useState(props.initNumber);

요렇게 하면 또 한 줄로 간단히 작성할 수 있겠지?

이상 함수형과 클래스형의 props와 state 사용법을 알아보았다~_~


출처: 생활코딩! 리액트 프로그래밍 책

profile
프론트엔드개발자가 되고 싶어서 열심히 땅굴 파는 자

0개의 댓글