js : javascript
x : 자바스크립트의 확장 문법
javascript + XML/HTML
React의 createElement() 함수
장점
사용법
{JavaScript 코드}...XML/HTMLconst element = < div tabIndex="0">< /div>;const element = < img src={user.avatarUrl}>< /img>;
import React from "react";
function Book(props){
return(
<div>
<h1>{`이 책의 이름은 ${props.name} 입니다.`}</h1>
<h2>{`이 책은 총 ${props.numOfPage}페이지로 이뤄져 있습니다.`}</h2>
</div>
);
}
export default Book;
import React from "react";
import Book from "./Book";
function Library(props){
return (
<div>
{/* 3개의 Book 컴포넌트를 렌더링 하고 있다. */}
<Book name="처음 만난 파이썬" numOfPage={300} />
<Book name="처음 만난 AWS" numOfPage={400} />
<Book name="처음 만난 리액트" numOfPage={500} />
</div>
);
}
export default Library;
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import reportWebVitals from './reportWebVitals';
// 라이브러리 컴포넌트 가져옴
import Library from './chapter_03/Library';
// 리액트 돔 사용하여 루트 돔 노드에 렌더링
ReactDOM.render(
<React.StrictMode>
<Library />
</React.StrictMode>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();



엘리멘트 생성 후에는 children, attribute 변경 불가새로운 엘리먼트를 만들어 기존과 바꿔치기 함(빠른 렌더링 속도 - Virtual DOM)Root DOM Node
<div id="root"></div>
리액트로만 만들어진 모든 웹사이트들은 단 하나의 루트 돔노드를 가짐

루트DIV에 리액트 엘리먼트를 렌더링하기 위해서 아래 코드 사용

엘리먼트 하나 생성 후 생성된 엘리먼트를 루트DIV에 렌더링. 렌더링 위해 리액트돔에 렌더라는 함수 사용.
렌더 함수의 1번째 파라미터 : React 엘리먼트
2번째 파라미터 : HTML 엘리먼트 - DOM 엘리먼트에 렌더링 하는 역할을 함
결국 React 엘리먼트가 렌더링되는 과정은 Virtual DOM에서 실제 DOM으로 이동하는 과정임
import React from "react";
// 현재 시간 출력하는 컴포넌트
function Clock(props){
return(
<div>
<h1>안녕, 리액트!</h1>
<h2>현재 시간 : {new Date().toLocaleTimeString()}</h2>
</div>
);
}
export default Clock;
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
// 라이브러리 컴포넌트 가져옴
import Library from './chapter_03/Library';
import Clock from './chapter_04/Clock';
// 리액트 돔 사용하여 루트 돔 노드에 렌더링
// setInterval 함수 사용해 1초마다 새롭게 clock 컴포넌트를 root.div에 rendering함
// 매 초 Clock 컴포넌트의 엘리먼트 새롭게 생성됨
setInterval(() => {
ReactDOM.render(
<React.StrictMode>
<Clock />
</React.StrictMode>,
document.getElementById('root')
);
}, 1000);
reportWebVitals();

리액트는 컴포넌트 기반의 구조
리액트에서는 모든 페이지가 컴포넌트로 구성되어 있고 하나의 컴포넌트는 또 다른 여러 개의 컴포넌트 조합으로 구성될 수 있다.
레고 블록 조립하듯 컴포넌트들을 모아 새로운 컴포넌트 만들 수 있다.
작은 컴포넌트들이 모여 하나의 컴포넌트를 구성하고 또 이런 컴포넌트들이 모여 전체 페이지를 구성한다.

하나의 컴포넌트를 반복 사용하여 전체 코드 양 줄일 수 있디 -> 개발시간, 유지보수 비용 감소
개념적으로 자바스크립트 함수와 비슷
Props가 출력은 React elements가 한다.리액트 컴포넌트의 속성
붕어빵에 들어가는 재료

각기 다른 이미지와 텍스트를 갖고 있는 것 - Props

Props는 컴포넌트에 전달할 다양한 정보를 담고 있는 자바스크립트 객체
특징
자바스크립트 함수의 속성


-> 리액트 컴포넌트의 정의와 관련되어 있다
모든 리액트 컴포넌트는 그들의 Props에 관해서는 Pure 함수 같은 역할을 해야 한다.
= 모든 리액트 컴포넌트는 Props를 직접 바꿀 수 없고, 같은 Props에 대해서는 항상 같은 결과(리액트 엘리먼트)를 보여줄 것
Props 사용법
<jsx의 경우>
중괄호 : 무조건 JavaScript 코드 들어간다.
Props에 값을 넣을 때도 문자열 이외 정수, 변수, 다른 컴포넌트 컴포넌트 등이 들어가면 중괄호로 감싸야 함(문자열로 중괄호로 감싸도 상관은 없음).


Props의 중괄호를 사용해 Props의 값으로 컴포넌트도 넣을 수 있다.
Layout 컴포넌트의 Props로는 정수 값을 가진 width, height와 react 엘리먼트로 header, footer가 들어오게 된다.

jsx 사용하면 간단하게 컴포넌트에 Props를 넣을 수 있다.
컴포넌트에는 클래스 컴포넌트와 함수 컴포넌트가 있다. 클래스가 불편함에 따라 나오게 된 함수 컴포넌트. 훅이 중요하다.
Function Component
모든 리액트 컴포넌트는 pure 함수 같은 역할 해야 함 = 리액트의 컴포넌트를 일종의 함수로 생각함.

간단한 코드를 가진다는 장점이 있다.
Class Component
JS ES6의 class 사용해 만들어진 형태의 컴포넌트.
함수 컴포넌트에 비해 몇 가지 추가적인 기능을 갖고 있다.
함수 컴포넌트와 가장 큰 차이점 : React의 모든 클래스 컴포넌트는 React.Component를 상속 받아 만든다.
상속 받았기 때문에 결과적으로 리액트 컴포넌트가 되는 것이다.

Component 이름
항상 대문자로 시작해야 한다.



웰컴 컴포넌트를 사용해서 컴포넌트 합성하는 예제 코드)
Props의 값을 다르게 해서 웰컴 컴포넌트 여러 번 사용함.


추출 예제 코드)

Avatar 추출

Props에 기존에 사용하던 author 대신 조금 더 보편적인 의미를 갖는 user로 변경(재사용성 측면 고려)

가독성 높아짐

UserInfo 추출




import React from "react";
function Comment(props) {
return (
<div>
<h1>제가 만든 첫 컴포넌트입니다.</h1>
</div>
)
}
export default Comment;
import React from "react";
import Comment from "./Comment";
function CommentList(props) {
return (
<div>
<Comment />
</div>
)
}
export default CommentList;
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
// 라이브러리 컴포넌트 가져옴
import Library from './chapter_03/Library';
import Clock from './chapter_04/Clock';
import CommentList from './chapter_05/CommentList';
// 리액트 돔 사용하여 루트 돔 노드에 렌더링
ReactDOM.render(
<React.StrictMode>
<CommentList />
</React.StrictMode>,
document.getElementById('root')
);
reportWebVitals();
import React from "react";
const styles = {
wrapper: {
margin: 8,
padding: 8,
display: "flex",
flexDirection: "row",
border: "1px solid grey",
borderRadius: 16,
},
imageContainer: {},
image: {
width: 50,
height: 50,
borderRadius: 25,
},
contentContainer: {
marginLeft: 8,
display: "flex",
flexDirection: "column",
justfyContent: "center",
},
nameTest: {
color: "black",
fontSize: 16,
fontWeight: "bold",
},
commentText: {
color: "black",
fontSize: 16,
},
};
function Comment(props) {
return (
<div style={styles.wrapper}>
<div style={styles.imageContainer}>
<img
src="https://upload.wikimedia.org/wikipedia/commons/8/89/Portrait_Placeholder.png"
style={styles.image}
/>
</div>
<div style={styles.contentContainer}>
<span style={styles.nameText}>이슬기</span>
<span style={styles.commentText}>
제가 만든 첫 컴포넌트입니다.
</span>
</div>
</div>
)
}
export default Comment;
import React from "react";
const styles = {
wrapper: {
margin: 8,
padding: 8,
display: "flex",
flexDirection: "row",
border: "1px solid grey",
borderRadius: 16,
},
imageContainer: {},
image: {
width: 50,
height: 50,
borderRadius: 25,
},
contentContainer: {
marginLeft: 8,
display: "flex",
flexDirection: "column",
justfyContent: "center",
},
nameTest: {
color: "black",
fontSize: 16,
fontWeight: "bold",
},
commentText: {
color: "black",
fontSize: 16,
},
};
function Comment(props) {
return (
<div style={styles.wrapper}>
<div style={styles.imageContainer}>
<img
src="https://upload.wikimedia.org/wikipedia/commons/8/89/Portrait_Placeholder.png"
style={styles.image}
/>
</div>
<div style={styles.contentContainer}>
<span style={styles.nameText}>{props.name}</span>
<span style={styles.commentText}>{props.comment}</span>
</div>
</div>
)
}
export default Comment;
Props를 사용하도록 comment 컴포넌트를 변경하면 아래 그림과 같이 아무 내용도 나오지 않게 된다. name과 comment 값이 정의되지 않아 undefined이기 때문.

import React from "react";
import Comment from "./Comment";
function CommentList(props) {
return (
<div>
<Comment name={"이슬기"} comment={"안녕하세요, 슬기입니다."}/>
</div>
)
}
export default CommentList;
수정 시 코멘트 컴포넌트의 props로 입력한 네임과 코멘트 값이 전달되어 아래처럼 내용이 표시된다.

import React from "react";
import Comment from "./Comment";
function CommentList(props) {
return (
<div>
<Comment name={"이슬기"} comment={"안녕하세요, 슬기입니다."}/>
<Comment name={"유재석"} comment={"리액트 재밌어요~~"}/>
</div>
)
}
export default CommentList;

import React from "react";
import Comment from "./Comment";
const comments = [
{
name: "이슬기",
comment: "안녕하세요. 슬기입니다."
},
{
name: "유재석",
comment: "리액트 재밌어요~~"
},
{
name: "김지유",
comment: "저도 리액트 배워보고 싶어요!"
}
]
function CommentList(props) {
return (
<div>
{comments.map((comment) => {
return (
<Comment name={comment.name} comment={comment.comment} />
);
})}
</div>
);
}
export default CommentList;
