DEVELOP
article thumbnail

1. React

# React 

:  사용자 정의 태그를 만드는 기술 

-  자바스크립트의 라이브러리

-  사용자 정의 인터페이스를 만들기 위해 사용 

-  https://ko.reactjs.org/

 

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></> }

결과예시

 

profile

DEVELOP

@JUNGY00N