React 실습 - props & state
버튼 실습을 통해 React 컴포넌트의 props와 state를 이해해 봅니다.
React 컴포넌트란, javascript 함수로 이해하면 되는데 이 때 입력이 props, 출력이 HTML 엘리먼트라고 생각하면 됩니다.
Props란, 컴포넌트를 호출한 부모 컴포넌트로부터 받은 파라미터로서 변경할 수 없는 값입니다.
State란, 컴포넌트 내에서 변경 가능한 정보로, state가 갱신되면 출력도 갱신됩니다.
자, 이제 예제 코드를 보면서 이해해 봅시다.
예제 코드:  Github 링크
소스 위치: src/tutorial/Tutorial01-ButtonClick.js
결과를 먼저 볼까요?
위 예제 코드를 받아 실행 후 브라우저에서 http://localhost:3000/test01 로 접속하면 아래와 같은 화면이 나옵니다.
이때, <be Jedi> 버튼을 클릭하면 아래 화면으로 갱신(제다이로 변신)합니다.
Props & State
Props는 부모 컴포넌트로부터 받은 값으로, 자식 컴포넌트에서 변경할 수 없습니다. State는 컴포넌트의 상태 값으로, 해당 컴포넌트 내에서 얼마든지 변경할 수 있으며, state 값이 변경되면 출력인 HTML 엘리먼트, 즉 앱 화면이 갱신됩니다.
이제 소스 코드를 살펴봅시다.
import React from 'react';
import { Badge, Button } from 'reactstrap';
const ANSWER_AT_HOME = "I am your son.";
const ANSWER_AS_JEDI = "May force be with you.";
function ButtonClickTest(props) {
const [message, setMessage] = React.useState(ANSWER_AT_HOME);
const handleClick = () => {
setMessage(message === ANSWER_AT_HOME ? ANSWER_AS_JEDI : ANSWER_AT_HOME);
}
return (
<div style={{ margin: '1em' }}>
<h2>Button Click Test</h2>
<div style={{ padding: '1em' }}>
<Button color="info" onClick={handleClick}>
{message !== ANSWER_AT_HOME ? "at Home" : "be Jedi"}
</Button>
<div style={{ padding: '2em' }}>
<p><Badge color="warning">Props</Badge> "{props.message}"</p>
<p><Badge color="success">State</Badge> "{message}"</p>
</div>
</div>
</div>
);
}
export default ButtonClickTest;
위 코드에는 나와있지 않지만, App.js에서 이 ButtonClickTest를 호출할 때 다음과 같이 props 값을 넘겨줍니다.
import TestButtonClick from './ui/Test01-ButtonClick.js';
...
<TestButtonClick message="I am your father."/>
...
위에서처럼 message 값을 넘기면, 자식 컴포넌트에서는 props.message로 참조할 수 있습니다. (return의 Line 8)
State 값은 컴포넌트 안에서 정의하고 사용하는데, React Hook 문법에서는 아래 발췌한 것과 같이 useState를 사용해 초기화 및 값을 참조/갱신할 수 있습니다.
예제에서는 message라는 state 변수를 썼는데 props.message와는 서로 무관합니다.
이 message 값은 setMessage() 함수를 통해서만 갱신할 수 있는데 setMessage()가 호출되면 message가 변경되면서 return() 내 구문도 갱신됩니다. 즉, 화면 상에서 State : message 부분이 갱신되는 것입니다.
const [message, setMessage] = React.useState(ANSWER_AT_HOME);
...
return (
...
<p><Badge color="success">State</Badge> "{message}"</p>
...
)
Tip> 이때, 페이지 전체가 업데이트되는 것이 아니라 props나 state에 관련된 부분만 업데이트되는데, 바로 이러한 원리가 React 앱을 효율적이고 안정적이게 합니다. 이러한 컴포넌트 기반의 장점을 예로 들자면, 페이스북에서 좋아요 버튼이 오류가 나면, 전통적인 웹페이지에서는 화면 전체에 500 internal server error 같은 오류를 띄우고 모든 것을 중단하지만, 컴포넌트 기반에서는 좋아요 버튼만 비활성화되고 나머지 컴포넌트들은 영향을 받지 않습니다. 최근 트렌디한 마이크로서비스 아키텍처와 같은 개념이라고 보시면 됩니다.
정리하면, props는 부모에게 받아 변경할 수 없는 값, state는 언제든 변경할 수 있는 내 맘대로 값!
버튼 동작
이제 버튼 동작을 살펴봅시다. 널리 알려진 UI 라이브러리, reactstrap의 버튼 컴포넌트를 사용했습니다.
- Reactstrap에 대한 자세한 내용은: React - UI 라이브러리
import { Badge, Button } from 'reactstrap';
...
<Button color="info" onClick={handleClick}>
{message !== ANSWER_AT_HOME ? "at Home" : "be Jedi"}
</Button>
일반적으로 onClick은 웬만한 HTML 엘리먼트에서 사용할 수 있는 속성으로, 이 엘리먼트를 클릭했을 때 발생하는 이벤트입니다. onClick에 함수를 넣으면 클릭 이벤트가 발생했을 때 해당 함수를 호출하게 됩니다.
예제에서는 버튼이 눌렸을 때 handleClick() 함수를 호출합니다.
const handleClick = () => {
setMessage(message === ANSWER_AT_HOME ? ANSWER_AS_JEDI : ANSWER_AT_HOME);
}
클릭을 하면 setMessage()를 통해 현재 message 값을 변경합니다. 언급한 것처럼 state가 변경되면 출력도 갱신됩니다. 따라서 버튼을 클릭하면 결과 화면의 message가 바뀌면서 문구와 버튼명이 바뀝니다.
참고로 위 함수는 람다 함수인데요, => 기호를 이용해서 함수를 축약할 수 있는 문법입니다. 버튼 코드에 바로 넣으면 코드가 한결 간결해지죠. 보통 한 줄짜리 코드를 짧게 압축해서 사용합니다.
<Button color="info" onClick={() => setMessage(message === ANSWER_AT_HOME ? ANSWER_AS_JEDI : ANSWER_AT_HOME)}>
{message !== ANSWER_AT_HOME ? "at Home" : "be Jedi"}
</Button>
음, 예제 코드에서는 람다 함수로 넣기엔 조금 지저분해 보이긴 하네요.