글쓰기 기능 만들기
유저 글쓰기 유아이 빌딩 합니다.
export default function 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: "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++) {
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></Create>;
}
return (
<div className="App">
<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>
);
}
Completion
<a href="/create" onClick={event=>{
event.preventDefault();
setMode('CREATE');
}}>Create</a>
펑션앱 리턴 가장 아래 콘텐트 데이터 아래
크리에이트 유아이를 만듭니다.
에이 태그 디폴트 액션 막습니다.
스테이트 변경 코드를 세팅합니다.
{/* 새로운 내용을 생성하는 링크입니다. */}
<a href="/create" onClick={event=>{
// 기본 동작(링크 클릭 시 페이지 이동)을 방지합니다.
event.preventDefault();
// 클릭 시 mode를 'CREATE'로 변경하여 Create 폼을 보여주게 합니다.
setMode('CREATE');
}}>Create</a>
else if(mode === 'CREATE') {
content = <Create></Create>
}
펑션앱 리턴 위
글쓰기를 탭했을 때 뷰를 바꿀 준비를 합니다.
크리에이트 태그를 변수로 만들어 준비하면 됩니다.
else if(mode === 'CREATE') {
// mode가 'CREATE'이면 Create 폼을 보여주는 Create 컴포넌트를 할당합니다.
content = <Create></Create>
}
펑션크리에잇 추가 합니다.
function Create() {
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>
)
}
펑션앱 바로 위
유저가 사용할 글쓰기 유아이를 펑션으로 추가합니다.
// Create 컴포넌트를 정의합니다. 이 컴포넌트는 새로운 내용을 생성하는 폼을 담당합니다.
function Create() {
return (
// HTML의 article 태그를 사용합니다.
<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>
)
}
test


크리에이트 링크 탭해서 글쓰기 유아이 잘 나오는지 체크합니다.
글 작성 후 데이터를 전달 합니다.
export default function 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: "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++) {
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) => {}}></Create>;
}
return (
<div className="App">
<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>
);
}
Completion
else if(mode === 'CREATE') {
content = <Create onCreate={(_title, _body)=>{
}}></Create>
}
펑션앱 모드크리에이트 내부
크리에이트 버튼을 탭했을 때 프롭에 펑션을 전달해야 합니다.
속성인 타이틀과 파라미터로 받은 타이틀은 헷갈리지 않도록 언더스코어로 구분 합니다.
바디도 마찬가지입니다.
else if(mode === 'CREATE') {
// 'mode'가 'CREATE'일 경우, 새로운 글을 작성하는 Create 컴포넌트를 할당합니다.
// Create 컴포넌트가 폼 제출 시 호출할 'onCreate' 함수를 props로 전달합니다.
content = <Create onCreate={(_title, _body)=>{
}}></Create>
}
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>
);
}
Completion
function Create(props)
펑션크리에이트
데이터를 전송 받기 위해 파라미터로 프롭스 사용 합니다.
<form onSubmit={event=>{
event.preventDefault();
const title = event.target.title.value;
const body = event.target.body.value;
props.onCreate(title, body);
}}>
펑션크리에이트 폼태그
유저가 작성한 제목과 내용을 변수에 저장해서 메서드 콜합니다.
{/* <form> 태그는 사용자 입력을 받는 폼을 생성합니다. */}
{/* onSubmit 이벤트 핸들러는 폼이 제출될 때 실행될 함수를 정의합니다. */}
<form onSubmit={event=>{
// 폼 제출 시 페이지가 새로고침되는 기본 동작을 방지합니다.
event.preventDefault();
// 폼 필드의 값을 가져옵니다. event.target은 폼 자체를 가리키며,
// name 속성(title, body)을 통해 해당 input/textarea 요소에 접근합니다.
const title = event.target.title.value;
const body = event.target.body.value;
// 부모 컴포넌트(App)로부터 전달받은 onCreate 함수를 호출하며,
// 새로 입력받은 제목과 내용을 인자로 전달하여 새로운 토픽을 생성하도록 지시합니다.
props.onCreate(title, body);
}}>
전달 받은 데이터 세이브 합니다.
export default 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++) {
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);
}}
></Create>
);
}
return (
<div className="App">
<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>
);
}
Completion
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 ...'}
]);
펑션앱 상단 토픽스 변수
토픽스 데이터를 스테이트로 변경 합니다.
// 'topics' 상태는 애플리케이션에서 다룰 글(토픽)들의 목록을 배열 형태로 저장합니다.
// useState를 통해 이 데이터가 상태로 관리되어 변경 시 화면이 다시 렌더링됩니다.
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 ...'}
]);
content = <Create onCreate={(_title, _body)=>{
const newTopic = {title:_title, body:_body}
}}></Create>
펑션앱 모드크리에이트 콘텐트변수
유저가 쓴 새 글을 오브젝에 저장해야 합니다.
// 새로운 토픽 객체를 생성합니다.
const newTopic = {title:_title, body:_body}
const [nextId, setNextId] = useState(4);
펑션앱 상단 아이디변수 아래
새글 저장할 준비를 하다 보니 글 아이디도 필요하겠네요.
글이 새로 생긴다면 글 아이디도 스테이트로 변경하는게 맞을것 같습니다.
원래 데이터가 3개 있으니 4부터 시작하는게 좋겠습니다.
// 'nextId' 상태는 새로운 토픽이 생성될 때 할당될 다음 ID 값을 관리합니다.
// 기존 토픽의 ID가 1, 2, 3이므로 초기값은 4입니다.
const [nextId, setNextId] = useState(4);
const newTopic = {id:nextId, title:_title, body:_body}
펑션앱 모드크리에이트 콘텐트변수 뉴토픽변수
아이디를 세팅했으니 새글 오브젝에 아이디도 추가합니다.
// 새로운 토픽 객체를 생성합니다. nextId를 사용하여 고유한 ID를 부여합니다.
const newTopic = {id:nextId, title:_title, body:_body}
const newTopics = [...topics]
newTopics.push(newTopic);
setTopics(newTopics);
펑션앱 모드크리에이트 콘텐트변수 뉴토픽변수 아래
리액트는 원시데이터 타입이 변경되면 잘 알아봅니다.
하지만 오브젝이나 어레이 데이터가 변경되면 잘 몰라봅니다.
그래서 오브젝이나 어레이의 경우는 복제해서 그것으로 교체합니다.
그러면 잘 알아봅니다.
즉, 오브젝이나 어레이는 복제본을 들이대야 리액트가 알아 챕니다.
// 기존 'topics' 배열을 불변성(immutability)을 유지하면서 새로운 배열을 만듭니다.
// 전개 연산자(...topics)를 사용하여 기존 배열의 모든 요소를 복사한 뒤,
// 새로 생성한 'newTopic'을 추가합니다.
const newTopics = [...topics]
newTopics.push(newTopic);
// 'topics' 상태를 새롭게 생성된 'newTopics' 배열로 업데이트합니다.
setTopics(newTopics);
test

타이틀과 내용을 입력하고 크리에잇 탭합니다.
잘 작동하는지 체크합니다.
새글 세입하면 알아서 새글보기로 이동하는 것이 좋겠습니다.
export default 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++) {
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="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>
);
}
Completion
setMode('READ');
setId(nextId);
setNextId(nextId+1);
펑션앱 모드크리에이트 콘텐트변수 셋토픽스메서드 아래
모드를 읽기로 변경하고 새글 아이디를 세팅하고 다음 아이디도 미리 세팅합니다.
// 새로운 토픽 생성 후, 해당 토픽의 내용으로 즉시 이동하여 보여주기 위해 모드를 'READ'로 변경합니다.
setMode('READ');
// 방금 생성된 토픽의 ID를 현재 읽을 토픽의 ID로 설정합니다.
setId(nextId);
// 다음 번에 생성될 토픽의 ID를 1 증가시킵니다.
setNextId(nextId+1);
test

Completion
import "./styles.css";
import { useState } from "react";
function Header(props) {
console.log("props", props.title);
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"></input>
</p>
</form>
</article>
);
}
export default 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++) {
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="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>
);
}
Comment ver
// styles.css 파일을 가져와 애플리케이션의 스타일을 적용합니다.
import "./styles.css";
// React의 useState 훅을 가져와 함수형 컴포넌트에서 상태를 관리할 수 있도록 합니다.
import { useState } from "react";
/**
* Header 컴포넌트: 애플리케이션의 상단 영역을 담당합니다.
* @param {object} props - 컴포넌트에 전달되는 속성 객체입니다.
* @param {string} props.title - 헤더에 표시될 제목입니다.
* @param {function} props.onChangeMode - 제목 클릭 시 호출될 콜백 함수입니다.
*/
function Header(props) {
// props.title 값을 콘솔에 출력하여 디버깅 용도로 사용합니다.
console.log("props", props.title);
return (
<header>
<h1>
{/* 헤더 제목 링크: 클릭 시 기본 동작을 막고 onChangeMode 함수를 호출하여 페이지 모드를 변경합니다. */}
<a
href="/"
onClick={(event) => {
event.preventDefault(); // 기본 링크 동작(페이지 새로고침)을 방지합니다.
props.onChangeMode(); // 부모 컴포넌트로부터 전달받은 모드 변경 함수를 호출합니다.
}}
>
{props.title} {/* props로 전달받은 제목을 표시합니다. */}
</a>
</h1>
</header>
);
}
/**
* Nav 컴포넌트: 내비게이션 메뉴를 렌더링합니다.
* @param {object} props - 컴포넌트에 전달되는 속성 객체입니다.
* @param {Array<object>} props.topics - 내비게이션 항목으로 사용될 주제(topic) 배열입니다. 각 객체는 id, title, body를 포함합니다.
* @param {function} props.onChangeMode - 내비게이션 항목 클릭 시 호출될 콜백 함수입니다. 선택된 항목의 id를 인자로 전달합니다.
*/
function Nav(props) {
const lis = []; // 내비게이션 리스트 아이템(<li>)을 저장할 배열입니다.
// props로 전달받은 topics 배열을 순회하며 리스트 아이템을 생성합니다.
for (let i = 0; i < props.topics.length; i++) {
let t = props.topics[i]; // 현재 topic 객체를 가져옵니다.
lis.push(
// 각 topic에 대한 리스트 아이템을 생성합니다.
<li key={t.id}>
{/* 내비게이션 링크: 클릭 시 기본 동작을 막고 onChangeMode 함수를 호출합니다. */}
<a
id={t.id} // 링크의 id를 topic의 id로 설정하여 클릭 이벤트에서 접근할 수 있도록 합니다.
href={"/read/" + t.id} // 링크의 URL을 설정합니다.
onClick={(event) => {
event.preventDefault(); // 기본 링크 동작(페이지 이동)을 방지합니다.
// 부모 컴포넌트로부터 전달받은 모드 변경 함수를 호출하며, 클릭된 항목의 id를 숫자로 변환하여 전달합니다.
props.onChangeMode(Number(event.target.id));
}}
>
{t.title} {/* topic의 제목을 링크 텍스트로 표시합니다. */}
</a>
</li>
);
}
return (
<nav>
<ol>{lis}</ol> {/* 생성된 리스트 아이템들을 정렬된 리스트(<ol>)로 렌더링합니다. */}
</nav>
);
}
/**
* Article 컴포넌트: 메인 콘텐츠 영역을 담당합니다.
* @param {object} props - 컴포넌트에 전달되는 속성 객체입니다.
* @param {string} props.title - 아티클의 제목입니다.
* @param {string} props.body - 아티클의 본문 내용입니다.
*/
function Article(props) {
return (
<article>
<h2>{props.title}</h2> {/* props로 전달받은 제목을 표시합니다. */}
{props.body} {/* props로 전달받은 본문 내용을 표시합니다. */}
</article>
);
}
/**
* Create 컴포넌트: 새로운 게시글을 생성하기 위한 폼을 렌더링합니다.
* @param {object} props - 컴포넌트에 전달되는 속성 객체입니다.
* @param {function(string, string): void} props.onCreate - 폼 제출 시 호출될 콜백 함수입니다. 제목과 본문 내용을 인자로 전달합니다.
*/
function Create(props) {
return (
<article>
<h2>Create</h2> {/* 'Create' 제목을 표시합니다. */}
{/* 폼 제출 시 기본 동작을 방지하고, 입력된 제목과 본문으로 onCreate 콜백 함수를 호출합니다. */}
<form
onSubmit={(event) => {
event.preventDefault(); // 폼 제출 시 페이지 새로고침을 방지합니다.
// 폼 요소의 name 속성을 이용하여 입력된 제목과 본문 내용을 가져옵니다.
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>
);
}
/**
* App 컴포넌트: 애플리케이션의 메인 엔트리 포인트입니다.
* 전체 UI를 구성하고 상태를 관리합니다.
*/
export default function App() {
// 현재 애플리케이션의 모드를 관리하는 상태 변수입니다 (예: "WELCOME", "READ", "CREATE").
const [mode, setMode] = useState("WELCOME");
// 현재 선택된 topic의 ID를 관리하는 상태 변수입니다.
const [id, setId] = useState(null);
// 새로운 topic에 할당될 다음 ID를 관리하는 상태 변수입니다.
const [nextId, setNextId] = useState(4);
// 내비게이션 및 콘텐츠를 구성하는 데 사용될 주제(topic) 데이터 배열입니다.
// useState를 사용하여 상태로 관리되므로, 데이터 추가 시 리렌더링이 발생합니다.
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; // 현재 모드에 따라 렌더링될 메인 콘텐츠 컴포넌트를 저장할 변수입니다.
// 현재 mode 상태에 따라 다른 콘텐츠를 렌더링합니다.
if (mode === "WELCOME") {
// mode가 "WELCOME"일 경우, 환영 메시지를 담은 Article 컴포넌트를 렌더링합니다.
content = <Article title="Welcome" body="Hello, Web"></Article>;
} else if (mode === "READ") {
// mode가 "READ"일 경우, 선택된 topic의 내용을 담은 Article 컴포넌트를 렌더링합니다.
let title,
body = null;
// topics 배열을 순회하여 현재 선택된 id와 일치하는 topic을 찾습니다.
for (let i = 0; i < topics.length; i++) {
if (topics[i].id === id) {
title = topics[i].title; // 해당 topic의 제목을 가져옵니다.
body = topics[i].body; // 해당 topic의 본문 내용을 가져옵니다.
}
}
content = <Article title={title} body={body}></Article>; // 찾은 topic 내용으로 Article 컴포넌트를 렌더링합니다.
} else if (mode === "CREATE") {
// mode가 "CREATE"일 경우, Create 컴포넌트를 렌더링하여 새 글 작성을 허용합니다.
content = (
<Create
onCreate={(_title, _body) => {
// Create 컴포넌트에서 전달받은 제목과 본문으로 새로운 topic 객체를 생성합니다.
const newTopic = { id: nextId, title: _title, body: _body };
// 기존 topics 배열을 복사하여 불변성을 유지하고 새 topic을 추가합니다.
const newTopics = [...topics];
newTopics.push(newTopic);
setTopics(newTopics); // 업데이트된 topics 배열로 상태를 변경합니다.
setMode("READ"); // 새 글 생성 후 "READ" 모드로 전환합니다.
setId(nextId); // 새로 생성된 글의 ID를 현재 선택된 ID로 설정합니다.
setNextId(nextId + 1); // 다음 글 작성을 위해 nextId를 1 증가시킵니다.
}}
></Create>
);
}
return (
<div className="App">
{/* Header 컴포넌트를 렌더링하고, 제목은 "WEB"으로 설정합니다. */}
{/* onChangeMode 프롭스에 콜백 함수를 전달하여 클릭 시 mode를 "WELCOME"으로 변경하도록 합니다. */}
<Header
title="WEB"
onChangeMode={() => {
setMode("WELCOME");
}}
></Header>
{/* Nav 컴포넌트를 렌더링하고, topics 데이터를 전달합니다. */}
{/* onChangeMode 프롭스에 콜백 함수를 전달하여 클릭 시 mode를 "READ"로, id를 선택된 topic의 ID로 변경하도록 합니다. */}
<Nav
topics={topics}
onChangeMode={(_id) => {
setMode("READ");
setId(_id);
}}
></Nav>
{/* 현재 mode에 따라 동적으로 결정된 content 컴포넌트를 렌더링합니다. */}
{content}
{/* "Create" 링크: 클릭 시 기본 동작을 막고 mode를 "CREATE"로 변경하여 글쓰기 폼을 표시합니다. */}
<a
href="/create"
onClick={(event) => {
event.preventDefault(); // 기본 링크 동작(페이지 이동)을 방지합니다.
setMode("CREATE"); // 모드를 "CREATE"로 설정하여 새 글 작성 폼을 표시합니다.
}}
>
Create
</a>
</div>
);
}

'생활코딩! React 리액트 프로그래밍' 카테고리의 다른 글
| egoing - React - delete (0) | 2025.06.25 |
|---|---|
| egoing - React - update (0) | 2025.06.24 |
| egoing - React - state (0) | 2025.06.23 |
| egoing - React - event (0) | 2025.06.21 |
| egoing - React - props - array (0) | 2025.06.21 |