React. 컴포넌트 만들기, Props, state
※본 포스팅은 생활코딩님의 리액트 강의를 바탕으로 작성한 글입니다.
컴포넌트 만들기
HTML로 코드를 작성했을 때
<html>
<body>
<header>
<h1>WEB</h1>
world wide web!
</header>
<nav>
<ul>
<li><a href="1.html">HTML</a></li>
<li><a href="2.html">CSS</a></li>
<li><a href="3.html">JavaScript</a></li>
</ul>
</nav>
<article>
<h2>HTML</h2>
HTML is Hyper Text Markup Language.
</article>
</body>
</html>
컴포넌트를 만드는 코드
class App extends Component {
render() {
return (
<div className="App">
Hello, React!
</div>
)
}
}
리액트가 가지고 있는 컴포넌트라는 클래스를 상속해서 새로운 App라는 클래스를 만든다
그리고 그 클래스는 render라는 매서드를 가지고 있다.
위 HTML 코드를 React로 정리하면
class Subject extends Component {
render() {
return (
<header>
<h1>WEB</h1>
world wide web!
</header>
);
}
}
class TOC extends Component {
render() {
return (
<nav>
<ul>
<li><a href="1.html">HTML</a></li>
<li><a href="2.html">CSS</a></li>
<li><a href="3.html">JavaScript</a></li>
</ul>
</nav>
);
}
}
class Content extends Component {
render() {
return (
<article>
<h2>HTML</h2>
HTML is Hyper Text Markup Language.
</article>
);
}
}
class APP extends Coponent {
render() {
return (
<div className="App">
<Subject></Subject>
<TOC></TOC>
<Content></Content>
</div>
);
}
}
자바스크립트 최신 문법에선 클래스 안에 들어가는 함수는 function 생략 가능하다.
컴포넌트를 만들 때는 반드시 하나의 최상위 태그를 가져야한다.
<Subject>, <TOC>와 같은 컴포넌트 이름에만 집중하게 함으로써 복잡도를 획기적으로 낮춤
위의 코드는 JSX로 자바스크립트랑 유사하게 생겼지만 자바스크립트는 아니다.
JSX로 코드를 작성하면 Create react app이 알아서 자바스크립트 코드로 변환해 줌
Props
html에서는 속성을 attribute라 하고 리액트에서 속성은 props라 함
컴포넌트에 속성을 부여하고 {this.props.속성이름}로 조회
class Subject extends Component {
render() {
return (
<header>
<h1>{this.props.title}</h1>
{this.props.sub}
</header>
);
}
}
Subject라는 컴포넌트는 언제나 똑같은 값을 출력해주는 것이었는데, title, sub와 같은 속성을 부여해 차별화를 준다. 이는 컴포넌트의 입력값이 됨으로써 다른 값을 출력할 수 있게 됨 -> 재사용성이 높아진다.
class App extends Component {
render() {
return (
<div className="App" >
<Subject title="WEB" sub="world wide web!"></Subject>
<Subject title="React" sub="For UI"></Subject>
<TOC></TOC>
<Content title="HTML" desc="HTML is Hyper Text Makrup Language."></Content>
</div>
);
}
}
컴포넌트 파일로 분리하기
수 많은 컴포넌트들이 하나의 파일 안에 있다면 얼마나 복잡할까?
각 컴포넌트들을 파일로 분리하면 코드가 간결해지고 필요한 컴포넌트를 빨리 찾을 수 있게 된다.
또한 다른 리액트 파일에서도 컴포넌트들을 재사용 할 수 있다.
src 디렉토리에 components 디렉토리를 생성
이 안에 각각의 컴포넌트 별로 파일을 만든다.
TOC.js
import React, { Component } from 'react'; // 컴포넌트를 TOC.js 안에 쓰기 위해 리액트를 불러오는 코드
class TOC extends Component {
render() {
return (
<nav>
<ul>
<li><a href="1.html">HTML</a></li>
<li><a href="2.html">CSS</a></li>
<li><a href="3.html">JavaScript</a></li>
</ul>
</nav>
);
}
}
export default TOC; // 이 코드로 인해서 TOC라는 클래스를 가져다 사용할 수 있게 됨
import React, { Component } from 'react'; // 리액트라는 라이브러리에서 컴포넌트라는 클래스를 로딩. 이를 밑에 component가 사용함
App.js
컴포넌트를 App.js으로 불러오는 코드
import TOC from "./components/TOC";
import Content from "./components/Content";
import Subject from "./components/Subject";
이후 App.js에 있던 TOC, Content, Subject 컴포넌트를 지워준다.
결과는 똑같지만 코드는 훨씬 보기 좋아진다.
State
Props는 사용자가 컴포넌트를 사용하는 입장에서 중요한 것이고,
State는 그 props의 값에 따라 내부의 구현에 필요한 데이터들, 사용자는 알 필요없는 컴포넌트 내부적으로 사용되는 것들
리액트와 같은 시스템이 컴포넌트를 만들고 그 컴포넌트가 좋은 부품이 되기 위해선 그 컴포넌트를 사용하는 외부의 props와 props에 따라 컴포넌트를 실제 구현하는 내부의 state라는 정보가 철저하게 분리 되어있어야한다.
사용하는 쪽과 구현하는 쪽 양쪽의 편의성을 각자 도모하는 것이 좋은 부품을 만드는 것의 핵심이고 리액트도 마찬가지이다.
state는 실제 컴포넌트를 구현할 때, 더 복합적으로 다양한 일들을 하는 컴포넌트를 만들 때 필요한 필수적인 요소
props를 쓰기 위해선 다음과 같은 코드가 필요함
어떠한 컴포넌트가 실행될 때 render 함수보다 먼저 실행이 되면서 그 컴포넌트를 초기화 시켜줌
class App extends Component{
constructor(props){
super(props);
this.state ={ // state 값을 초기화
subject : {title : 'WEB', sub : 'World Wide Web!'}
}
}
render() {
return (
<div className="App" >
<Subject title={this.state.subject.title}
sub={this.state.subject.sub}>
</Subject>
</div>
);
}
}
1. State 값을 초기화
2. subject의 프로퍼티값으로 'WEB'과 'World Wide Web'을 줌
3. 상위 컴포넌트 App의 state 값을 하위 컴포넌트의 props 값으로 전달
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
<App />, document.getElementById('root'));
);
reportWebVitals();
index.js를 보는 우리 입장에선 <App/>가 내부적으로 state값이 subject가 있는지 없는지 알수가 없다. 외부에서 알 필요가 없는 정보를 철저하게 은닉하는 것이 좋은 사용성을 만든다.