어플리케이션은 기본적으로 아래의 4가지 기능을 가지고 있다.
앞서 학습한 리액트 시작하기가 READ
기능에 해당한다.
이번에는 리액트의 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" // 1️⃣
onClick={(event) => {
event.preventDefault();
setMode("CREATE"); // 2️⃣
}}
>
Create - 새로운 항목을 생성하세요.
</a>
</div>
);
1️⃣ : 새로운 항목을 만드는 페이지로 이동하기 위한 링크
2️⃣ : 리액트는 SPA프레임워크
다 우리는 새로운 페이지를 생성하지 않고, 상태를 바꾸어서 해당 상태의 UI만 변경되도록 한다.
if (mode === "WELCOME") {
content = <Article title="Wellcome" body="Hello, React"></Article>;
} else if (mode === "READ") {
let title,
body = null;
topics.forEach((topic) => {
if (topic.id === id) {
title = topic.title;
body = topic.body;
}
});
content = <Article title={title} body={body}></Article>;
} else if (mode === "CREATE") {
content = <Create></Create>; // 3️⃣
}
3️⃣ : 상태(mode)가 "CREATE" 일 때 content UI는 컴포넌트 Create를 따른다.
export function Create() { // 4️⃣
return (
<article>
<h2>Create 페이지</h2>
<form> // 5️⃣
<p><input type="text" name="title" placeholder="title.."></input></p>
<p><textarea name="body" placeholder="body.."></textarea></p>
<p><input type="submit" value="Create!"></input></p>
</form>
</article>
);
}
4️⃣ : Create 컴포넌트 생성
5️⃣ : 사용자의 input값을 전달하므로 form 태그로 작성
export function Create(props) // 1️⃣ {
return (
<article>
<h2>Create 페이지</h2>
<form onSubmit={(event) => { // 2️⃣
event.preventDefault();
const title = event.target.title.value;
const body = event.target.body.value;
props.onCreate(title, body) // 3️⃣
}}>
<p><input type="text" name="title" placeholder="title.."></input></p>
<p><textarea name="body" placeholder="body.."></textarea></p>
<p><input type="submit" value="Create!"></input></p>
</form>
</article>
);
}
/////////////////////////
else if (mode === "CREATE") {
content = <Create onCreate= {(_title, _body) => {
}}></Create>;
}
1️⃣ : CREATE 상태일 때, 사용자 입력값을 가져와서 행동할 함수를 props로 전달
2️⃣ : 사용자 입력값을 전달하기 위해 "Create!" 제출시 onSubmit 함후 실행
3️⃣ : 사용자가 입력한 값(title, body)을 props함수에 전달한다.
Create 컴포먼트에서 입력받은 값들로 행동(CREATE)을 취한다.
function App() {
// 1️⃣
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..." },
]);
// 2️⃣
const [nextId, setNextId] = useState(4);
////////////////////////////////////////////////
else if (mode === "CREATE") {
content = (
<Create
onCreate={(_title, _body) => {
// 3️⃣
const newTopic = { id: nextId, title: _title, body: _body };
const newTopics = [...topics]; // 4️⃣
newTopics.push(newTopic);
setTopics(newTopics);
}}
></Create>
);
}
1️⃣ : 입력값으로 CREATE하고자 하는 것은 topic의 요소 추가다.
2️⃣ : 새로운 topic들의 id를 상태로 관리하기 위한 추가
3️⃣ : 입력받은 값들로 새로운 topic을 만든다.
4️⃣ : 상태 변경의 값이 범객체(object, arrat)라면 반드시 복제 후에 상태를 변경해주어야 한다.
리액트에서는 상태가 변경되면 (setMode등) 해당 컴포넌트를 다시 렌더링 해준다고 했다.
여기서 주의해야 할 점이 있다.
원시값이 아닌 객체의 상태 변경의 경우 리렌더링이 일어나지 않는다.
❗️ 원시값의 경우
const [value, setValue] = useState(1)
setValue(2)
-> 최초 value는 값 1이다.
-> setValue(2)로 value 값은 2가 되었다.
-> 리액트는 오리지날 값 1이 2로 변경됨을 감지하고 리렌더링 한다.
❗️ 범객체의 경우(obj, array 등)
const [value, setValue] = useState([1])
value.push(2)
setValue(value)
-> 최초 value는 [1]을 가진다.
-> value에 새로운 값 [2]를 추가하여 [1,2]가 되도록 한다.
-> [1,2]가 된 value를 setValue 해준다.
-> 리액트는 setValue(value)를 검토하지만, 오리지날 value만 검토한다.
-> 오리지날 value는 변경되지 않았기에 리렌더링이 일어나지 않는다.
객체의 상태변경의 경우
Spread 연산자
를 이용하여 복제 후 값을 변경하고
변경된 복제의 객체로 상태 변경을 요청해야 한다.
💡 범객체에서의 상태변경
const [value, setValue] = useState([1])
const newValue = [...value]
newValue.push(2)
setValue(newValue)
-> newValue는 오리지날 value와 값이 다르기에 리렌더링이 일어난다.
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);
setId(nextId); // 1️⃣
setMode("READ"); // 2️⃣
setNextId(nextId + 1); // 3️⃣
}}
></Create>
);
}
1️⃣ : CREATE된 요소의 ID를 현재 ID로 상태변경 해준다.
2️⃣ : mode의 상태를 "READ"로 변경해주면 CREATE된 항목의 "READ"로 바로 렌더링 된다. (id를 변경해 주었으므로)
3️⃣ : 새로 CREATE될 요소를 위해 nextId값을 1증가 시켜준다.