
1. React
# React
: 사용자 정의 태그를 만드는 기술
- 자바스크립트의 라이브러리
- 사용자 정의 인터페이스를 만들기 위해 사용
React – 사용자 인터페이스를 만들기 위한 JavaScript 라이브러리
A JavaScript library for building user interfaces
ko.reactjs.org
<javascript />npx create-react-app my-app cd my-app npm start
2. 컴포넌트
# 컴포넌트
: 사용자 정의 태그
- UI를 재사용이 가능한 개별적인 여러 조각으로 나누고 각 조각을 개별적으로 살펴볼 수 있음
- 이름의 시작은 항상 대문자
- 함수 컴포넌트 / 클래스 컴포넌트
- props 객체를 인자로 받고, 화면에 어떻게 보여줄 것인지를 기술하는 리액트 엘리먼트를 return
< 함수 컴포넌트 예시 >
<javascript />
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header>
<h1><a href ="/">WEB</a></h1>
</header>
<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>
<article>
<h2>Welcome</h2>
Hellp, WEB!
</article>
</div>
);
}
export default App;
<javascript />
import logo from './logo.svg';
import './App.css';
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>
}
function App() {
return (
<div className="App">
<Header></Header>
<Header></Header>
<Header></Header>
<Nav></Nav>
<Article></Article>
</div>
);
}
export default App;
3. 프로퍼티(Props)
# 프로퍼티(Props)
: 상위 컴포넌트가 하위 컴포넌트에게 값 전달시 사용 ( 단방향 데이터 흐름)
- 수정 불가 ( 하위 컴포넌트 기준에서 읽기 전용 데이터)
- 하위 컴포넌트에서 프로퍼티의 값을 이용해 리액트 엘리먼트를 작성하여 리턴함
- props는 (함수 매개변수처럼) 컴포넌트에 전달
< 프로퍼티 사용 예시 >
<javascript />
//import logo from './logo.svg';
import './App.css';
function Header(props) {
return <header>
<h1><a href="/">{props.title}</a></h1>
</header>
}
function Nav(props) {
const topicsList = [];
for (var i = 0; i < props.topics.length; i++) {
var t = props.topics[i];
topicsList.push(<li key={t.id}><a href={'/read/' + t.id}>{t.title}</a></li>);
}
return <nav>
<ol>
{topicsList}
</ol>
</nav>
}
function Article(props) {
return <article>
<h2>{props.title}</h2>
{props.body}
</article>
}
function App() {
const topics = [
{ id: 1, title: 'html', body: 'html is...' },
{ id: 2, title: 'css', body: 'css is...' },
{ id: 3, title: 'js', body: 'js is...' },
];
return (
<div className="App">
<Header title="React!!"></Header>
<Header title="RRR"></Header>
<Header title="EEE"></Header>
<Nav topics={topics}></Nav>
<Article title="Welcome" body="Hello,Web"></Article>
</div>
);
}
export default App;
4. 이벤트
# 이벤트
- preventDefault()를 호출해주어야 기본 동작 방지 가눙
<javascript />
<Header title="React!!" onchangeMode={() => {
alert('WELCOME');
}}></Header>
<javascript />
var Header = (props) => {
return <header>
<h1><a href="/" onClick={(event) => {
event.preventDefault(); //기본동작 방지
props.onchangeMode();
}}>{props.title}</a></h1>
</header>
}

5. state
# state
- 컴포넌트 내부에서 변경 가능한 데이터를 관리해야할 때 사용
- props는 (함수 매개변수처럼) 컴포넌트에 전달되어 값의 변경이 불가한 반면 state는 (함수 내에 선언된 변수처럼) 컴포넌트 안에서 관리하므로 값의 변경이 가능
- 보통 이벤트와 함께 사용
- 동적인 데이터를 다룰 때 사용
<state 사용 예시>
<javascript />
const [state, setState] = useState(initialState);
const [ 데이터, 데이터변경함수 ] = useState(초기값(생략가능));
- mode와 id를 state로 사용
<javascript />
//import logo from './logo.svg';
import './App.css';
import { useState } from 'react';
var Header = (props) => {
return <header>
<h1><a href="/" onClick={(event) => {
event.preventDefault(); //기본동작 방지
props.onchangeMode();
}}>{props.title}</a></h1>
</header>
}
var Nav = (props) => {
const topicsList = [];
for (var i = 0; i < props.topics.length; i++) {
var t = props.topics[i];
topicsList.push(<li key={t.id}><a id={t.id} href={'/read/' + t.id} onClick={(event)=>{
event.preventDefault();
props.onchangeMode(Number(event.target.id));
}}>{t.title}</a></li>);
}
return <nav>
<ol>
{topicsList}
</ol>
</nav>
}
var Article = (props) => {
return <article>
<h2>{props.title}</h2>
{props.body}
</article>
}
var App = () => {
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: 'js', body: 'js is...' },
];
var content = null;
if(mode==='WELCOME'){
content = <Article title='Welcome' body = 'Hello, WEB'></Article>
}else if(mode==='READ'){
let title, body = null;
for(var 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="React!!" onchangeMode={() => {
setMode('WELCOME');
}}></Header>
<Nav topics={topics} onchangeMode={(id)=>{
setMode('READ');
setId(id);
}}></Nav>
{content}
</div>
);
}
export default App;

6. Create 기능 추가
- 목록에 사용자가 직접 title과 body를 작성하여 추가
< Create 컴포넌트 >
- onSubmit() : submit(create)버튼 클릭 시 props.onCreate에 사용자가 작성한 title과 body값을 넘겨줌
<javascript />
var 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>
<input type="text" name="title" placeholder="title" />
</p>
<p>
<textarea name="body" placeholder='body'></textarea>
</p>
<p>
<input type="submit" value = "Create"/>
</p>
</form>
</article>
}
- topic 배열, 다음 id 값을 각각 state로 지정
- create 클릭 시 mode가 'CREATE'로 변경됨
- 새로운 id, title, body 내용을 담은 객체를 생성하고 원래의 topics객체에 push
- 이때 원래의 배열topics에 ... 을 붙여 기존배열을 새로운 배열로 복사하고, 새로운 객체를 push하여 setTopics함
- 다시 mode를 'READ'로 변경하고, 다음 id값, 현재 id값을 set함
- mode가 READ가 되었으므로 새로운 객체가 추가된 리스트가 화면에 출력
<javascript />
var App = () => {
const [mode, setMode] = useState('WELCOME');
const [id, setId] = useState(null);
const [topics, setTopics] = useState([
{ id: 1, title: 'html', body: 'html is...' },
{ id: 2, title: 'css', body: 'css is...' },
{ id: 3, title: 'js', body: 'js is...' },
]);
const [nextId, setNextId] = useState(topics.length);
var content = null;
if (mode === 'WELCOME') {
content = <Article title='Welcome' body='Hello, WEB'></Article>
} else if (mode === 'READ') {
let title, body = null;
for (var 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);
}}></Create>
}
return (
<div className="App">
<Header title="React!!" onchangeMode={() => {
setMode('WELCOME');
}}></Header>
<Nav topics={topics} onchangeMode={(id) => {
setMode('READ');
setId(id);
}}></Nav>
{content}
<a href="/create" onClick={(event) => {
event.preventDefault();
setMode("CREATE");
}}>Create</a>
</div>
);
}

7. Update(Edit, 값 수정)
- 사용자가 수정할 항목을 선택해 title과 body 값을 원하는 내용으로 수정하고, 수정한 결과를 화면에 출력
< Edit 컴포넌트>
- 원래의 값을 input 칸에 넣어야하는데 그냥 props에서 값을 추출하면 수정이 불가한 값이 됨
- props의 title과 body값을 각각 state로 바꿔서 수정가능하게 함
- onChange함수로 input 칸의 값이 수정될때마다 그 값을 각각 title과 body로 set함
- 수정된 title과 body값을 onEdit의 인자로 넘겨줌
<javascript />
var Edit = (props) => {
const [title, setTitle] = useState(props.title);
const [body, setBody] = useState(props.body);
return <article>
<h2>Edit</h2>
<form onSubmit={(event) => {
event.preventDefault();
const title = event.target.title.value;
const body = event.target.body.value;
props.onEdit(title, body);
}}>
<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);
}}></textarea>
</p>
<p>
<input type="submit" value="Edit" />
</p>
</form>
</article>
}
- contextControl으로 mode가 'WELCOME'일 때는 null이다가, 'READ' mode일 때만 Edit 버튼이 보이게 함
- onEdit의 인자로 받은 title과 body로 새 객체를 생성
- 기존 객체배열에서 수정한 객체를 새로운 객체로 바꾸고 mode를 'READ'로 바꿈
<javascript />
var App = () => {
const [mode, setMode] = useState('WELCOME');
const [id, setId] = useState(null);
const [topics, setTopics] = useState([
{ id: 1, title: 'html', body: 'html is...' },
{ id: 2, title: 'css', body: 'css is...' },
{ id: 3, title: 'js', body: 'js is...' },
]);
const [nextId, setNextId] = useState(topics.length);
var content = null;
var contextControl = null; // Read mode일때만 edit 보이도록
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={"/edit/" + id} onClick={(event) => {
event.preventDefault();
setMode('EDIT');
}}>Edit</a></li>
} 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);
}}></Create>
} else if (mode === 'EDIT') {
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 = <Edit title={title} body={body} onEdit={(title, body) => {
const newTopics =[...topics];
const editedTopic = {id:id, title:title, body:body}
for(let i = 0; i<topics.length; i++){
if(newTopics[i].id === id){
newTopics[i] = editedTopic;
break;
}
}
setTopics(newTopics);
setMode('READ');
}}></Edit>
}
return (
<div className="App">
<Header title="React!!" onchangeMode={() => {
setMode('WELCOME');
}}></Header>
<Nav topics={topics} onchangeMode={(id) => {
setMode('READ');
setId(id);
}}></Nav>
{content}
<ul>
<li><a href="/create" onClick={(event) => {
event.preventDefault();
setMode("CREATE");
}}>Create</a></li>
{contextControl}
</ul>
</div>
);
}

8. Delete
- 원하는 항목 선택 후 Delete 버튼 클릭시 해당 항목 삭제
- mode가 'READ'일 때 contextControl을 수정하여 delete 버튼 보이게 함
- delete 버튼 클릭하면 빈 배열 newTopics를 생성하고, 선택된 id 값의 객체를 제외한 다른 객체들을 빈 배열에 push
- 새로운 topics배열을 set하고, nextId를 현재 topics의 길이로 설정하고, mode를 'WELCOME'으로 바꿈
<javascript />
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={"/edit/" + id} onClick={(event) => {
event.preventDefault();
setMode('EDIT');
}}>Edit</a></li>
<li><input type="button" value = "Delete" onClick={()=>{
const newTopics = [];
for(let i=0; i<topics.length; i++){
if(topics[i].id !== id){
newTopics.push(topics[i]);
}
}
setTopics(newTopics);
setNextId(topics.length);
setMode('WELCOME');
}}/></li></>
}

'FRONTEND > React' 카테고리의 다른 글
[ 인프런 - 한입 크기로 잘라 먹는 React] 3. React 실전 프로젝트 - 감정 일기장 만들기(2) (0) | 2023.01.09 |
---|---|
[ 인프런 - 한입 크기로 잘라 먹는 React] 3. React 실전 프로젝트 - 감정 일기장 만들기(1) (0) | 2023.01.08 |
[ 인프런 - 한입 크기로 잘라 먹는 React] 2. React 기본 - 간단한 일기장 프로젝트 (2) (0) | 2023.01.06 |
[ 인프런 - 한입 크기로 잘라 먹는 React] 2. React 기본 - 간단한 일기장 프로젝트 (1) (0) | 2023.01.03 |
[ 인프런 - 한입 크기로 잘라 먹는 React ] 1. React 기초 (0) | 2022.12.30 |