리엑트는 사용자 정의 태그
를 만드는 기술이다.
// Header라는 정의태그를 만든다.
function Header() {
return (
<header>
<h1>
<a href="/">WEB</a>
</h1>
</header>
);
}
// Header라는 정의된 태그를 HTML에서 사용할 수 있다.
// 어디서는 Header라는 이름만으로 사용이 가능하다.
function App() {
return (
<div>
<Header></Header>
<Header></Header>
</div>
);
}
// 정의된 태그의 내용만 수정해도 사용된 페이지 전체의 Header가 자동으로 수정된다.
이 사용자 정의 태그를 리엑트에서는
컴포넌트
라고 부른다.
독립된
하나의 부품으로 생성가능하고function Header(props) {
return (
<header>
<h1>
<a href="/">{props.title}</a>
</h1>
</header>
);
}
function App() {
return (
<div>
<Header title="REACT"></Header>
</div>
);
}
// 하드코딩으로 만들어져있는 Nav 컴포넌트
function Nav() {
return (
<nav>
<ol>
<li><a href="/read/1">html</a></li>
<li><a href="/read/2">css</a></li>
<li><a href="/read/3">js</a></li>
</ol>
</nav>
);
}
function App() {
return (
<div>
<Nav></Nav>
</div>
);
}
// Props를 사용하여 동적으로 값을 주자.
function Nav(props) {
const lis = props.topics.map((topic) => {
// 동적으로 Nav태그의 li를 만들어 준다. 3️⃣
return (
// 동적으로 생성되는 Element에 key값 부여. 4️⃣
// 동적으로 topic id, title 전달. 5️⃣
<li key={topic.id}>
<a href={`/read/${topic.id}`}>{topic.title}</a>
</li>
);
});
return (
<nav>
<ol>{lis}</ol>
</nav>
);
}
function App() {
// Nav에 사용될 객체들이 존재한다고 했을 때, 1️⃣
const topics = [
{ id: 1, title: "html", body: "html is..." },
{ id: 2, title: "css", body: "css is..." },
{ id: 3, title: "js", body: "js is..." },
];
return (
// Nav Props로 사용할 객체를 전달해준다. 2️⃣
<div>
<Nav title={topics}></Nav>
</div>
);
}
🚫 4️⃣ 처럼 동적으로 태그를 생성 할 때는 리엑트가 추적이 가능하다록 고유의 키값을 넣어주어야 한다.
function Header(props) {
return (
<header>
<h1>
<a
href="/"
// onClick 이벤트 핸들러 추가. 2️⃣
onClick={(event) => {
event.preventDefault();
// props의 해당 이벤트 실행. 3️⃣
props.onChangeMode();
}}>
{props.title}
</a>
</h1>
</header>
);
}
function App() {
return (
<div>
<Header
title="REACT"
// Header 컴포넌트에 이벤트 Props 부여. 1️⃣
onChangeMode={function () {
alert("이벤트가 일어난다.");
}}
></Header>
</div>
);
}
const header = document.querySelector(".a")
// 1️⃣
const onChangeMode = () => {
alert("이벤트가 일어난다")
}
// 2️⃣, 3️⃣
header.addEventListener("click", onChangeMode)
컴포넌트는 입력
과 출력
이 있다.
앞서 배운 Prop이 입력값이다. 컴포넌트는 Prop을 받고 return을 반환한다.
Prop말고 return을 반환하는 것이 하나더 존재하는데 그것이 State
다.
새로운 return값을 만든다는 것은 UI를 바꾼다는 것이다.
즉, 컴포넌트는 Prop나 State로 부터 값을 받아서 UI를 변경한다.
예제로 돌아가서 변수 mode가 바뀌면 Article의 내용이 변하도록 만들어보자.
function Article(props) {
return (
<article>
<h2>{props.title}</h2>
{props.body}
</article>
);
}
function App() {
let mode = "Welcome";
let content = null;
// 변수 mode의 변경에 따라 content가 바뀌도록 구현
if (mode === "Welcome") {
content = <Article title="Welcom" body="Hello, Web"></Article>;
} else if (mode === "Read") {
content = <Article title="Read" body="Hello, Read"></Article>;
}
// Header 클릭시 mode는 'Welcome'
// Nav 클릭시 mode는 'Read'
return (
<div>
<Header
title="REACT"
onChangeMode={function () {
mode = "Welcome";
}}
></Header>
<Nav
topics={topics}
onChangeMode={() => {
mode = "Read";
}}
></Nav>
{content}
</div>
);
}
State
다.// state 사용을 위해서는 useState라는 훅을 가져와야 한다.
// 훅은 react에서 기본적으로 제공해주는 함수다.
import {useState} from 'react'
// state를 사용할 변수에 useState를 적용한다.
// useState를 사용한 변수명에는 _를 달아준다.
let _mode = useState("Welcome");
// _mode를 살펴보자
console.log(_mode)
0번째
원소는 상태의 값
가진다.1번째
원소는 상태의 값을 변경
할 때 사용되는 함수를 가진다.// _mode의 0번째, 1번째 원소들로 아래와 같이 사용할 수 있게 된다.
const mode = _mode[0] // 상태 값을 가진 변수
const setMode = _mode[1] // 상태 값을 변경하는 함수를 가진 함수
// 정리하여 mode라는 state를 사용한다면 아래와 같이 사용할 수 있다.
const [mode, setmode] = useState("Welcome")
위 예제를 state를 사용하여 다시 정리하면 아래와 같이 작성된다.
function App() {
// useState를 사용하여 상태값과 상태 변경 함수를 가져옴
const [mode, setMode] = useState("Welcome");
let content = null;
// 변수 mode의 상태 값에 따라 content가 바뀌도록 구현
if (mode === "Welcome") {
content = <Article title="Welcom" body="Hello, Web"></Article>;
} else if (mode === "Read") {
content = <Article title="Read" body="Hello, Read"></Article>;
}
// Header 클릭시 setMode('Welcome')
// Nav 클릭시 setMode는('Read')
return (
<div>
<Header
title="REACT"
onChangeMode={function () {
setMode("Welcome");
}}
></Header>
<Nav
topics={topics}
onChangeMode={() => {
setMode("Read");
}}
></Nav>
{content}
</div>
);
}
상태변경 함수
가 실행
되면 해당 컴포넌트
는 재실행
된다. → 렌더링이 일어난다.// 클릭된 Nav의 ID값(상태)에 따라 title과 body가 변하게 할 수도 있다.
function App() {
const [mode, setMode] = useState("Welcome");
// 상태를 사용하기 위한 id, setId
const [id, setId] = useState(null);
const topics = [
{ id: 1, title: "html", body: "html is..." },
{ id: 2, title: "css", body: "css is..." },
{ id: 3, title: "js", body: "js is..." },
];
let content = null;
// mode가 "Read"일때, 클릭된 Nav의 ID(상태)를 변경해준다.
if (mode === "Welcome") {
content = <Article title="Welcom" body="Hello, Web"></Article>;
} else if (mode === "Read") {
let title, body = null;
// 변경된 ID에 해당하는 title, body값을 가져온다.
topics.forEach((topic) => {
if (topic.id === id) {
title = topic.title;
body = topic.body;
}
});
content = <Article title={title} body={body}></Article>;
}
return (
<div>
<Header
title="REACT"
onChangeMode={function () {
setMode("Welcome");
}}
></Header>
<Nav
topics={topics}
onChangeMode={(_id) => {
// Nav를 클릭하면 mode가 변경되고
// 클릭된 Nav의 id로 setId 해준다.
// 그 후 App 컴포넌트는 재실행된다.
setMode("Read");
setId(_id);
}}
></Nav>
{content}
</div>
);
}