React에서는 컴포넌트라는 개념이 있다.
어떤 요소를 미리 만들어두고 여러 번 꺼내서 재사용할 수 있다.
만드는 방법은 클래스로 만드는 방법과 함수로 만드는 방법이 있다.
props라는 속성값을 이용하여 컴포넌트 안에서 쓰는 특정 값을 편하게 관리할 수 있다.
<body>
<p>-------------------root1--------------------------------</p>
<div id="root1">
</div>
<p>-------------------root2--------------------------------</p>
<div id="root2">
</div>
<p>-------------------root3--------------------------------</p>
<div id="root3">
</div>
<p>-------------------root4--------------------------------</p>
<div id="root4">
</div>
<p>-------------------root5--------------------------------</p>
<div id="root5">
</div>
<p>-------------------root6--------------------------------</p>
<div id="root6">
</div>
<!-- react cdn -->
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<!-- react dom cdn -->
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<!-- babel cdn -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<!-- define type as a babel -->
<script type="text/babel">
// -------------------root1--------------------------------
// 함수 컴포넌트
// 개념적으로 컴포넌트는 JavaScript 함수와 유사하다.
// “props”라고 하는 데이터를 임의로 넣어준 뒤에, 그 데이터가 화면에 어떻게 표시되는지를 알려주는 React 엘리먼트를 반환한다.
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const user = {name: 'Tom', career: 'actor'}
ReactDOM.render(Welcome(user), document.getElementById('root1') );
// -------------------root2--------------------------------
// 클래스 컴포넌트
// JavaScript ES6 의 class 문법을 사용하여 컴포넌트를 정의할 수도 있다.
// React의 관점에서 볼 때 위 두 가지 유형의 컴포넌트는 동일하다.
class Greetings extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
ReactDOM.render(<Greetings name="Ben" />, document.getElementById('root2') );
// -------------------root3--------------------------------
// 컴포넌트가 렌더링되는 과정
// 지금까지는 DOM 태그만을 사용해 React 엘리먼트를 나타냈다.
const eleOld = <div> <h1> This is old element </h1> </div>;
// React 엘리먼트는 사용자 정의 컴포넌트로도 나타낼 수 있다.
const eleNew = <Greetings name="Sara" />;
// React가 사용자 정의 컴포넌트로 작성한 엘리먼트를 발견하면 해당 컴포넌트에 JSX 어트리뷰트와 하위 요소들을 단일 객체로 전달한다. 이 객체를 “props”라고 한다.
ReactDOM.render(eleNew, document.getElementById('root3') );
// 이 예시에서는 다음과 같은 일들이 일어납니다.
// 1. <Greetings name="Sara" /> 엘리먼트로 ReactDOM.render()를 호출한다.
// 2. React는 {name: 'Sara'}를 props로 두고 Greetings 컴포넌트를 호출한다.
// 3. Greetings 컴포넌트는 결과적으로 <h1>Hello, Sara</h1> 엘리먼트를 내놓는다.
// 4. React DOM은 <h1>Hello, Sara</h1> 엘리먼트와 일치하도록 DOM을 효율적으로 업데이트한다.
// 주의: React는 소문자로 시작하는 컴포넌트를 DOM 태그로 처리한다. ex) <div> <input> <img>
// 따라서 컴포넌트는 대문자로 시작해야 한다. ex) <Greetings> <MyCompo> <ProductList>
// -------------------root4--------------------------------
// 컴포넌트 합성하기
// 컴포넌트는 자신의 출력에 다른 컴포넌트를 참조할 수 있다.
// React 앱에서는 버튼, 폼, 다이얼로그, 화면 등의 모든 것들이 흔히 컴포넌트로 표현된다.
// 예를 들어 SayHello를 여러 번 렌더링하는 App 컴포넌트를 만들 수 있다.
function SayHello(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<SayHello name="Leo" />
<SayHello name="Bruce" />
<SayHello name="Ethan" />
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('root4')
);
// -------------------root5--------------------------------
// 컴포넌트 추출하기
// 다음 Comment 컴포넌트는 author(객체), text(문자열), date(날짜)를 props로 받은 후 소셜 미디어 웹 사이트의 코멘트를 반환한다.
function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<img className="Avatar"
src={props.author.avatarUrl}
alt={props.author.name}
/>
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
function formatDate(date) {
return date.toLocaleTimeString();
}
const user5 = {
author: {
avatarUrl:'hello-world',
name: 'Sam'
},
text: 'Hello World',
date: new Date()
};
ReactDOM.render(Comment(user5), document.getElementById('root5'))
// 위 Comment 컴포넌트는 구성 요소들이 모두 중첩 구조로 이루어져 있어서 변경하기 어렵다.
// 각 구성요소를 개별적으로 재사용하기도 힘들다.
// 이 컴포넌트에서 몇 가지 컴포넌트를 떼어내 보자.
// 먼저 Avatar를 추출해 보자.
// Avatar 는 자신이 Comment 내에서 렌더링 된다는 것을 알 필요가 없다.
// 따라서 props의 이름을 author에서 더욱 일반화된 user로 변경했다.
// props의 이름은 사용될 context가 아닌 컴포넌트 자체의 관점에서 지어야 좋다.
function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name} />
);
}
// 이렇게 만든 Avatar 컴포넌트를 활용하여 Comment 컴포넌트를 다시 구성해 보자.
function Comment2(props) {
return (
<div className="Comment">
<div className="UserInfo">
<Avatar user={props.author} />
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
// 다음으로 Avatar 옆에 사용자의 이름을 렌더링하는 UserInfo 컴포넌트를 추출해 보자.
function UserInfo(props) {
return (
<div className="UserInfo">
<Avatar user={props.user} />
<div className="UserInfo-name">
{props.user.name}
</div>
</div>
);
}
// UserInfo 컴포넌트를 활용하여 Comment 컴포넌트를 다시 구성해 보자.
function Comment3(props) {
return (
<div className="Comment">
<UserInfo user={props.author} />
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
// -------------------root6--------------------------------
ReactDOM.render(Comment3(user5), document.getElementById('root6'));
// Comment 컴포넌트가 아까보다 훨씬 간단해졌다.
// 처음에는 컴포넌트를 추출하는 작업이 지루해 보일 수 있다.
// 하지만 구현하려는 앱이 커지면 커질수록 재사용 가능한 컴포넌트를 만들어 놓는 일이 중요해진다.
// -------------------root7--------------------------------
// 컴포넌트가 가지는 props 자체를 수정해서는 안 된다.
// 함수 컴포넌트든 클래스 컴포넌트든 모두 마찬가지다.
// 예를 들어 아래 함수를 보자.
function sum(a, b) {
return a + b;
}
// 위 함수는 입력받은 값 a와 b 자체는 바꾸려 하지 않는다.
// 그 값을 가공하여 그 결과값을 반환한다.
// 이처럼 입력 받은 값을 바꾸지 않는 함수를 순수 함수라고 한다.
// 반면에 아래와 같은 함수들은 입력 받은 값 자체를 수정하거나 변경하기 때문에 순수 함수가 아니다.
function withdraw(account, amount) {
account.total -= amount;
}
// React는 매우 유연하지만 한 가지 엄격한 규칙이 있다.
// 모든 React 컴포넌트는 자신의 props를 다룰 때 반드시 순수 함수처럼 동작해야 한다.
</script>
</body>
- 220524
참고자료 -
반응형
'React' 카테고리의 다른 글
React 시작하기 - 06 - 이벤트 핸들링하기, this 바인딩 해주기, e 합성 이벤트 (0) | 2022.06.18 |
---|---|
React 시작하기 - 05 - 컴포넌트 안에서 state와 생명 주기 활용하기 (0) | 2022.06.18 |
React 시작하기 - 03 - 리액트에서 엘리먼트 다루기와 루트 돔 변화 (0) | 2022.06.18 |
React 시작하기 - 02 - jsx 개념과 리액트 엘리먼트 (0) | 2022.06.18 |
React 시작하기 - 01 - 가장 간단한 형태의 리액트 요소 (0) | 2022.06.18 |