Coding Feature.

React #7 Create, <form> 태그 본문

생활코딩 독학/WEB2 - JS React

React #7 Create, <form> 태그

codingfeature 2023. 1. 10. 16:17

CRUD

Create

Read

Update

Delete

 

먼저 Create 링크를 클릭하면 모드가 create 모드로 바뀌어 UI가 변경되는 것을 구현.

<a href="/create" onClick={event=>{
event.preventDefault();
setMode('CREATE');
}}>Create</a>

 

그리고

else if(mode === 'CREATE'){

content = <Create></Create>

}

를 추가.

이때 content 내용이 많으므로 Create 컴포넌트를 새롭게 코딩.

 

<form>이라는 html 태그를 이용할 것.

form 태그는 서버에 사용자 입력 정보를 전송할 때 사용된다.

<form action="(사용자 입력 정보가 보내질 주소)">
<p>아이디 : <input type="text" name="id"></p>
<p>비밀번호 : <input type="password" name="pwd"></p>
<p>주소 : <input type="text" name="address"></p>
<input type="submit">
</form>

이때 input type이 password인 경우, 글자 대신 **과 같은 별이 보인다.

input type이 submit일 때, 제출 버튼이 생성된다.

action= 뒤에 쓰여질 주소에 위의 정보가 전송된다.

그리고 submit 버튼을 누를 때 그 주소로 이동한다.

name= 뒤에 이름을 작성해서 각 정보를 구분한다.

 

function Create(props){
return <article>
<h2>Create</h2>
<form>
<p><input type="text" name="title" placeholder="title"/></p>
<p><textarea name="body" placeholder="body"></textarea></p>
<p><input type="submit" value="Create"></input></p>
</form>
</article>
}
textarea 태그는 여러 줄이 적힐 창.
placeholder는 글 작성 이전에 보여지는 글씨.
 
그 다음 Create 컴포넌트 사용시 onCreate prop에 인자 title과 body를 받는 함수가 실행되는 것을 작성한다.
<Create onCreate={(_title, _body)=>{
..
}}>
 
앞서 작성한 form 태그에
<form onSubmit={event=>{
event.preventDefault();
const title = event.target.title.value;
const body = event.target.body.value;
props.onCreate(title, body);
}}>
 
위와 같이
제출 버튼을 클릭해도 새로운 페이지로 이동하지 않게 하고,
event.target 즉 제출 이벤트 발생 시 form의 태그 내 정보를 이용해서
event.target.title.value와 event.target.body.value로
사용자가 입력한 title, body 값을 받아들인다.
이후 onCreate 함수 인자로 넘겨준다.

 

그 다음 구현해야 할 것은

topics 배열에 사용자가 입력한 정보를 할당하는 것.

따라서 topics에 useState를 사용해 state로 승격시켜야 한다.

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 ...'}
]);

 

앞으로 추가될 Id를 관리하기 위해 nextid state를 추가한다.

const [nextId, setNextId] = useState(4);
state의 초기값이 4인 이유는 이미 id가 3까지 쓰였기 때문.
 

content = <Create onCreate={(_title, _body)=>{

const newTopic = {id:nextId, title:_title, body:_body}
topics.push(newTopic);
setTopics(topics);
setMode('READ');
setId(nextId);
setNextId(nextId+1);
}}></Create>
setMode('READ');-> setmode를 read로 하여 제출 후 작성한 내용이 보이도록 하고
setId(nextId);
setNextId(nextId+1);
->각 Id state를 새로 업데이트한다.
push로 새 객체를 topics 배열에 넣고
setTopics() 함수를 사용하여 topics state를 업데이트하면 될 것이다.
그러나 위 내용은 동작하지 않는다.

 

이에 대해서는 

JavaScript Immutability (opentutorials.org)

 

JavaScript Immutability

수업소개 자바스크립트에서 데이터를 불변하게 다루는 방법에 대한 수업입니다. 이 수업에서는 아래와 같은 내용을 다루고 있습니다.  원시 데이터 타입과 객체의 동작방법 간의 차이 객체를

opentutorials.org

를 참고할 것.

간단히 소개하면

string, number, boolean과 같은 Primitive형 데이터를 useState 사용 시 그대로 쓰면 되지만,

object, array와 같은 Object형 데이터는

{...value}, [...value]

를 통해 newValue로 이전 value 값을 복제하고

newValue 값을 설계대로 변경 후

newValue로 setValue 해주어야 한다.

React는 primitive형 데이터 변경 시 다른 것을 확인하고 리로드를 하지만

object형 데이터 내부 원소 변경 시 배열, 객체와 같은 틀 자체는 다르지 않으므로 따로 리로드를 하지 않는다.

따라서 동작을 안 하는 것.

 

결국

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>
를 해주어야 한다.

 

 

결국 최종 코드는 다음과 같다.

import {useState} from 'react';
 
function Article(props){
return <article>
<h2>{props.title}</h2>
{props.body}
</article>
}
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 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"></input></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++){
console.log(topics[i].id, id);
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>
<Header title="WEB" 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>
);
}
 
export default App;

'생활코딩 독학 > WEB2 - JS React' 카테고리의 다른 글

React #6 state  (0) 2023.01.10
React #5 이벤트  (0) 2023.01.10
React #4 props  (0) 2023.01.10
React #3 사용자 정의 태그 만들기.  (0) 2023.01.10
React #2 Source 코드 수정, 배포  (0) 2023.01.10