🔹 create 버튼 아래에 update 버튼 생성 및 태그 정리
<ul>
<li>
<a href='/create' onClick={event => {
event.preventDefault();
setMode('CREATE');
}}>Create</a>
</li>
<li>
<a href='/update'>Update</a>
</li>
</ul>
🔹 상세보기에서만 update 버튼이 노출되기 위해 mode가 'READ' 인 경우에만 태그를 뿌려준다.
// 변수선언
let contextControl = null;
// mode 가 'READ'일 떄만 contextControl 에 태그 추가
// 링크에 id값도 추가
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}>Update</a></li>
}
// 실제 위치에는 변수사용
<ul>
<li>
<a href='/create' onClick={event => {
event.preventDefault();
setMode('CREATE');
}}>Create</a>
</li>
{contextControl}
</ul>
🔹 update 버튼에 클릭이벤트를 넣고 setMode('Update') 를 실행하여 해당 컴포넌트로 연결한다.
// click event 추가
contextControl = <li><a href={'/update/'+id} onClick={event => {
event.preventDefault();
setMode('UPDATE');
}}>Update</a></li>
// else if 문 추가해서 컴포넌트 연결
// 클릭 시 동작하는 함수도 추가 해 준다
else if (mode === 'UPDATE') {
content = <Update onUpdate={(title, body) => {
// 아직 내용 없음
}}></Update>
}
🔹 update 컴포넌트를 생성 해 준다.
( Create 컴포넌트 복사해와서 텍스트, Value값, 함수명을 수정해따 )
function Update (props) {
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);
}}>
<p><input type='text' name='title' placeholder='title'/></p>
<p><textarea name='body' placeholder='body'></textarea></p>
<p><input type='submit' value='Update'/></p>
</form>
</article>
)
}
🔹 mode === 'READ' if문에서 클릭된 id값의 title, body값을 추출하는 코드를 가져온다.
🔹 거기서 title, body 값을 Update 컴포넌트의 props로 넣어준다.
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) => {
}}></Update>
}
🔹 그리고 넘어온 props를 Update 컴포넌트에서 value값에 넣어준다.
// Update 컴포넌트 form 태그 내부
<p><input type='text' name='title' placeholder='title' value={props.title}/></p>
<p><textarea name='body' placeholder='body' value={props.body}></textarea></p>
<p><input type='submit' value='Update'/></p>
🔸 그럼 요로케 Read한 값이 뜨지만 props로 넘어온 값이기 때문에 변경할 수는 없다.
🔸 그래서 props를 state로 변경한다..!
// Update 상단에서 state 선언
const [title, setTitle] = useState(props.title);
const [body, setBody] = useState(props.body);
// 해당 state를 value에 사용
<p><input type='text' name='title' placeholder='title' value={title}/></p>
<p><textarea name='body' placeholder='body' value={body}></textarea></p>
하지만 이렇게해도 값은 바뀌지않는다.
state가 변하지 않았기 때무네..!
싑지안내 😇
🔸 그래서 onChange 함수를 추가 해 준다.
( 우선 log를 찍어본다 )
<p><input type='text' name='title' placeholder='title' value={title} onChange={event => {
console.log(event.target.value);
}}/></p>
🔸 그러면 우선 요로케 아직 UI에 값이 변하지는 않지만 입력값이 log에 찍힌다
( 1,2,3 차례로 입력함 )
🔹 그리고 value값으로 setTitle을 실행한다
<p><input type='text' name='title' placeholder='title' value={title} onChange={event => {
setTitle(event.target.value);
}}/></p>
와우 드디어...🥹
어려우니까 다시 정리 👏
props로 받아온 title을 state로 환승
=> 그 state를 input의 value값으로 지정
=> onChange로 키보드를 입력할 때 마다 setTitle의 값을 지정
=> 그때마다 title이 바뀌고 컴포넌트가 랜더링됨
=> 그 새로운 값이 value값으로 들어감
🔸 그렇게 body값도 바꿔본다
// Update 컴포넌트
function Update (props) {
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);
}}>
<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='Update'/></p>
</form>
</article>
)
}
🔸 이제 Submit 하면 title과 body를 담아서 onUpdate 함수가 실행되고,
🔸 함수 실행 부분에서 log를 찍어보면
// mode 'UPDATE' 부분
content = <Update title={title} body={body} onUpdate={(title, body) => {
console.log(title, body);
}}></Update>
입력한 값이 잘 찍힌다
🔹 그럼 이제 요기에다가 Create 때 했던 것처럼 배열을 복제해서 update 시켜준다
🔸 현재 id값과 동일한 id값을 가진 배열을 교체 해 준다
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;
}
}
// 배열 리로드 해 주고, 해당 id값의 상세페이지로 보내기
setTopics(newTopics);
setMode('READ');
}}></Update>
끗 - 😎
// import './App.css';
import {useState} from 'react';
function Header(props) {
return (
<header>
<h1>
<a href="/" onClick={(event) => {
event.preventDefault();
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(Number(event.target.id));
}}>{t.title}</a>
</li>
)
}
return (
<nav>
<ol>
{lis}
</ol>
</nav>
);
}
function Article(props) {
return (
<article>
<h2>{props.title}</h2>
{props.body}
</article>
);
}
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><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>
)
}
function Update (props) {
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);
}}>
<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='Update'/></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;
let contextControl = 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>
contextControl = <li><a href={'/update/'+id} onClick={event => {
event.preventDefault();
setMode('UPDATE');
}}>Update</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 === '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');
}}></Update>
}
return (
<div className="App">
<Header title='WEB' 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>
);
}
export default App;