npx create-react app . // 현재 디렉토리에 프로젝트 생성
npm start
코드 시행
npm run build
serve: 웹서버. 사용 추천. 노드.
npx serve -s build
=> localhost 말고 네트워크로 배포.
사용자 정의 태그 만들기: 함수 정의 (무조건 대문자)
=> 컴포넌트
// components
function Header() {
return <header>
<h1><a href = "/">React</a></h1>
</header>
}
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 Article() {
return <article>
<h2>Welcome</h2>
Hello, WEB
</article>
}
// main function
function App() {
return (
<div className="App">
<Header />
<Nav />
<Article />
</div>
);
}
Prop: 속성
function Header(props) { // 변수명 임의로 props라 설정함
console.log('props', props, props.title);
return <header>
<h1><a href = "/">{props.title}</a></h1>
// { } 안에 작성 시, 변수 취급
</header>
}
function App() {
return (
<div className="App">
<Header title = 'REACT'/>
<Nav />
<Article />
</div>
);
}
콘솔에 다음과 같이 출력됨
>> props {title: 'REACT'} REACT
function Nav(props) {
const lis = []
// 반복문
for(let i = 0; i < props.topics.length; i++){ // 객체 배열 길이: length
let t = props.topics[i]; // topics 배열을 변수 t에 저장
lis.push(<li key = {t.id}> // key라는 prop에는 unique key값 필요. id 값을 key 값으로 저장
<a href = {"/read/" + t.id}>{t.title}</a>
// 중괄호 사용하여 id값을 주소에 포함
// title을 내용으로 함
</li>)
}
return <nav>
<ol>
{lis}
</ol>
</nav>
}
function App() {
const topics = [ // 객체 배열 생성
{id : 1, title: 'html', body: 'html is...'},
{id : 2, title: 'css', body: 'css is...'},
{id : 3, title: 'javascript', body: 'javascript is...'}
]
return (
<div className="App">
<Header title = 'WEB'/>
<Nav topics = {topics}/>
<Article title = 'Welcome' body = 'Hello, WEB'/>
</div>
);
}
function Header(props) {
console.log('props', props, props.title);
return <header>
<h1><a href = "/" onClick = {(event) => { // callback 함수. arrow function
event.preventDefault(); // 기본 동작 방지 => 클릭해도 리로드 X
props.onChangeMode();
}}>{props.title}</a></h1>
</header>
}
function Nav(props) {
const lis = []
for(let i = 0; i < props.topics.length; i++){
let t = props.topics[i];
lis.push(<li key = {t.id}>
<a id = {t.id} href = {"/read/" + t.id} onClick = {(event) => {
event.preventDefault();
props.onChangeMode(event.target.id);
// event 객체가 가지고 있는 event를 유발시킨 태그 : target
}}>
{t.title}</a>
</li>)
}
return <nav>
<ol>
{lis}
</ol>
</nav>
}
function App() {
//
return (
<div className="App">
<Header title = 'WEB' onChangeMode = {() => {
alert('Header');
}}/>
<Nav topics = {topics} onChangeMode = {(id) => {
alert(id);
}}/>
<Article title = 'Welcome' body = 'Hello, WEB'/>
</div>
);
}
prop: 컴포넌트를 사용하는 외부자를 위한 data
state: 컴포넌트를 만드는 내부자를 위한 data
import { useState } from 'react';
function Nav(props) {
const lis = []
for(let i = 0; i < props.topics.length; i++){
let t = props.topics[i];
lis.push(<li key = {t.id}>
// t.id는 원래 숫자. 하지만 태그의 속성에 들어가는 순간 문자가 됨.
<a id = {t.id} href = {"/read/" + t.id} onClick = {(event) => {
event.preventDefault();
props.onChangeMode(Number(event.target.id));
// Number로 변환 안 해주면 문자열 값.
}}>
{t.title}</a>
</li>)
}
return <nav>
<ol>
{lis}
</ol>
</nav>
}
function App() {
/*
const _mode = useState('WELCOME'); // 초기값 설정
const mode = _mode[0]; // 상태의 값을 읽음
const setMode = _mode[1]; // 상태의 값을 변경할 때 사용하는 함수
console.log('_mode', _mode);
*/
const [mode, setMode] = useState('WELCOME'); // 간단하게 표현
const [id, setId] = useState(null);
const topics = [
{id : 1, title: 'html', body: 'html is...'},
{id : 2, title: 'css', body: 'css is...'},
{id : 3, title: 'javascript', body: 'javascript is...'}
]
let content = null;
if (mode === 'WELCOME'){
content = <Article title = 'Welcome' body = 'Hello, WEB'></Article>
} else if (mode === 'READ') {
let title, body = null;
for(let i = 0; i < topics.length; i++){
if(topics[i].id === id){
title = topics[i].title;
body = topics[i].body;
}
}
content = <Article title = {title} body = {body}></Article>
}
return (
<div className="App">
<Header title = 'WEB' onChangeMode = {() => {
setMode('WELCOME');
}}/>
<Nav topics = {topics} onChangeMode = {(id) => {
setMode('READ');
}}/>
{content}
</div>
);
}
function Create(props) {
return <article>
<h2>Create</h2>
<form onSubmit = {(event) => {
event.preventDefault();
const title = event.target.title.value;
const body = event.target.body.value;
props.onCreate(title, body);
}}>
// 각각 다른 줄에 표현하기 위해 p 태그 사용
<p><input type = 'text' name = 'title' placeholder = 'title' /></p>
<p><textarea name = 'body' placeholder = 'body' /></p>
<p><input type = 'submit' value = 'Create' /></p>
</form>
</article>
}
function App() {
const [mode, setMode] = useState('WELCOME');
const [id, setId] = useState(null);
const [nextId, setNextId] = useState(4);
const [topics, setTopics] = useState([
{id : 1, title: 'html', body: 'html is...'},
{id : 2, title: 'css', body: 'css is...'},
{id : 3, title: 'javascript', body: 'javascript is...'}
]);
let content = null;
if (mode === 'WELCOME'){
content = <Article title = 'Welcome' body = 'Hello, WEB'></Article>
} else if (mode === 'READ') {
let title, body = null;
for(let i = 0; i < topics.length; i++){
if(topics[i].id === id){
title = topics[i].title;
body = topics[i].body;
}
}
content = <Article title = {title} body = {body}></Article>
} else if (mode === 'CREATE') {
content = <Create onCreate = {(_title, _body) => {
const newTopic = {id: nextId, title: _title, body: _body}
const newTopics = [...topics] // 복제본 생성
newTopics.push(newTopic);
setTopics(newTopics);
setMode('READ');
setId(nextId);
setNextId(nextId + 1);
}}/>
}
return (
<div className="App">
<Header title = 'WEB' onChangeMode = {() => {
setMode('WELCOME');
}}/>
<Nav topics = {topics} onChangeMode = {(_id) => {
setMode('READ');
setId(_id);
}}/>
{content}
<a href = '/create' onClick = {(event) => {
event.preventDefault();
setMode('CREATE');
}}>Create</a>
</div>
);
}
function Update(props) {
// useState 사용하여 업데이트
const [title, setTitle] = useState(props.title);
const [body, setBody] = useState(props.body);
return <article>
<h2>Update</h2>
<form onSubmit = {(event) => {
event.preventDefault();
const title = event.target.title.value;
const body = event.target.body.value;
props.onUpdate(title, body);
}}>
// onChange 속성 함수로 변경 내용 실시간 반영
<p><input type = 'text' name = 'title' placeholder = 'title' value = {title} onChange = {(event) => {
setTitle(event.target.value);
}}/></p>
<p><textarea name = 'body' placeholder = 'body' value = {body} onChange = {(event) => {
setBody(event.target.value);
}}/></p>
<p><input type = 'submit' value = 'Update' /></p>
</form>
</article>
}
function App() {
//
let content = null;
let contextControl = null; // READ 모드일 때만 확인 가능한 context
if (mode === 'WELCOME'){
content = <Article title = 'Welcome' body = 'Hello, WEB'></Article>
} else if (mode === 'READ') {
let title, body = null;
for(let i = 0; i < topics.length; i++){
if(topics[i].id === id){
title = topics[i].title;
body = topics[i].body;
}
}
content = <Article title = {title} body = {body}></Article>
contextControl = <li><a href = {'/update/' + id} onClick = {(event) => {
event.preventDefault();
setMode('UPDATE');
}}>Update</a></li>
} else if (mode === 'CREATE') {
//
} else if (mode === 'UPDATE') {
let title, body = null;
for(let i = 0; i < topics.length; i++){
if(topics[i].id === id){
title = topics[i].title;
body = topics[i].body;
}
}
content = <Update title = {title} body = {body} onUpdate = {(title, body) => {
const newTopics = [...topics]
const updatedTopic = {id: id, title: title, body: body}
for(let i = 0; i < newTopics.length; i++){
if(newTopics[i].id === id){
newTopics[i] = updatedTopic;
break;
}
}
setTopics(newTopics);
setMode('READ');
}}/>
}
return (
//
<ul>
<li><a href = '/create' onClick = {(event) => {
event.preventDefault();
setMode('CREATE');
}}>Create</a></li>
{contextControl}
</ul>
</div>
);
}
else if (mode === 'READ') {
let title, body = null;
for(let i = 0; i < topics.length; i++){
if(topics[i].id === id){
title = topics[i].title;
body = topics[i].body;
}
}
content = <Article title = {title} body = {body}></Article>
contextControl = <>
<li><a href = {'/update/' + id} onClick = {(event) => {
event.preventDefault();
setMode('UPDATE');
}}>Update</a></li>
<li><input type = 'button' value = 'Delete' onClick = {() => {
const newTopics = []
for(let i = 0; i < topics.length; i++){
// 현재 id에 해당하지 않는 topics의 id들만 newTopics 배열에 push
if(topics[i].id !== id){
newTopics.push(topics[i]);
}
}
setTopics(newTopics);
setMode('WELCOME');
}} /></li>
</>
}
생활코딩 React 강의 2022 개정판
https://youtu.be/AoMv0SIjZL8