완성본
맨 위의 Header부분인 React를 클릭하면
<Article title="Hi!!!" body="Let's start"></Article>;
Article의 title과 body를 가져온다
Nav부분인 1. html~ 3. js를 클릭하면
const details = [
{ id: 1, title: "html", body: "h내용입니다." },
{ id: 2, title: "css", body: "c내용입니다." },
{ id: 3, title: "js", body: "j내용입니다." },
];
클릭한 Nav의 id값이 details의 id와 같으면 그 id에 해당하는 객체의 title과 body값을 Article로 가져온다
<Article title={title} body={body}></Article>
전체코드
import "./App.css";
import { useState } from "react";
// useState : 태그의 상태를 변경시켜주는 리액트 hook
// 리액트는 속성을 prop이라고 한다
function Header(props) {
/* Header를 props라는 객체로 만들어준것 */
/* 리액트의 함수명 첫글자는 꼭 대문자로 */
return (
<header>
<h1>
<a
href="/"
onClick={(event) => {
event.preventDefault(); //페이지 새로고침 방지
props.onChangeMode();
}}
>
{props.title}
</a>
</h1>
</header>
);
}
// 가운데 1.html 2.css 3.js
function Nav(props) {
let lis = props.details.map((item) => {
return (
<li key={item.id}>
<a
id={item.id}
// a id={item.id}를 넣지않아도 동작하는데 굳이 넣는이유? → 실제로 개발할 때 예시를 들면,
// item.id라는 것은 스크롤을 내리면서 여러 군데를 봐야 이것이 뭘 의미하는 지 정확히 이해할 수 있습니다.
// 하지만 event.target.id로 쓰게 되면 '바로 위에 있는 a태그의 id값을 나타내는 구나', 라고 바로 이해할 수 있습니다.
//item.id를 가져올때는 숫자로 가져왔지만 태그의 속성으로 넘기면서 문자열이 된다
href={"/read/" + item.id} //"/read/"는 왜 넣는걸까??? url
onClick={(event) => {
event.preventDefault();
props.onChangeMode(Number(event.target.id));
//item.id를 가져올때는 숫자로 가져왔지만 태그의 속성으로 넘기면서 문자열이 된다 → 숫자로 바꿔줌
}}
>
{item.title}
</a>
{/* 리액트는 자동으로 생성하는 태그의 경우 추적을 위해 key라는 속성을 부여해줘야한다 */}
</li>
);
});
return (
<nav>
<ol>{lis}</ol>
</nav>
);
}
function Article(props) {
return (
<article>
<h3>{props.title}</h3>
{props.body}
</article>
);
}
function App() {
// const total = useState('Hi');
// const mode = total[0];
// const setMode = total[1];
const [mode, setMode] = useState("Hi"); // 이 코드는 위의 세줄과 같다
//useState("Hi")를 console.log해보면 ['Hi', f(함수)]으로 나온다
const [id, setId] = useState(null);
const details = [
{ id: 1, title: "html", body: "h내용입니다." },
{ id: 2, title: "css", body: "c내용입니다." },
{ id: 3, title: "js", body: "j내용입니다." },
];
let content = null;
if (mode === "Hi") {
content = <Article title="Hi!!!" body="Let's start"></Article>;
} else if (mode === "Read") {
//Article에 details의 body를 넣어줘야한다
//여기서 id값은 Nav의 setId(idVal)값을 가져오는것이다
//idVal값은 function Nav()의 <a id={item.id}></a>에서 가져온다
let title,
body = null;
details.map((ele) => {
if (ele.id === id) {
title = ele.title;
body = ele.body;
}
return (content = <Article title={title} body={body}></Article>);
});
}
return (
<div>
{/* 컴포넌트 첫글자 대문자로 */}
<Header
title="React"
onChangeMode={() => {
setMode("Hi"); // 값을 바꿀때는 setMode를 사용
}}
></Header>
<Nav // 가운데 1.html 2.css 3.js 부분
details={details}
onChangeMode={(idVal) => {
setMode("Read"); //Nav를 클릭했을때 mode값을 "Read"로 변경해준다
setId(idVal); // Nav를 클릭했을때 그 클릭한 요소의 id값으로 id를 변경해준다
//idVal값은 function Nav()의 <a id={item.id}></a>에서 가져온다
}}
></Nav>
{content}
</div>
);
}
export default App;
map() 사용시 주의할 점
let content = null;
if (mode === "Hi") {
content = <Article title="Hi!!!" body="Let's start"></Article>;
} else if (mode === "Read") {
let title, body = null;
details.map((ele) => {
if (ele.id === id) {
title = ele.title;
body = ele.body;
}
});
return (content = <Article title={title} body={body}></Article>);
}
map은 조건에 맞는 요소를 배열로 반환하는 함수인데 위의 코드를 보면
return값이 없다. 위의 코드에서는 return문이 details.map() 밖에 나와있고 map안에는 if문과 title, body에 대입하는 식만 존재함
let content = null;
if (mode === "Hi") {
content = <Article title="Hi!!!" body="Let's start"></Article>;
} else if (mode === "Read") {
let title, body = null;
details.map((ele) => {
if (ele.id === id) {
title = ele.title;
body = ele.body;
}
return (content = <Article title={title} body={body}></Article>);
});
}
return문을 detail.map()안으로 옮겨주고 해결