https://deahan.tistory.com/429
까지 읽었다면 , 웹 프로그램을 해본 경험이 있는 사람은 조금이나마
느낌이란 게 분명 있었을 거다. (없다면 당신은 프론트 경험이 없는 거나 마찬가지..)
오늘은 레이아웃을 해보려 한다..
CSS 지식만 조금 있다면, CSS 특성상 시간이 조금 걸릴뿐 이해는 쉽다.
기존 껀 지저분해졌으니... 새로 시작하는 마음으로 새롭게 시작해 보자.
REACTSTUDY 폴더에서 복습겸 새로 프로젝트를 만들고, 개발 서버를 구동하자.
npm create vite@lateste
Project name: rlayout
Select a framework: React
Select a variant: JavaScript
cd rlayout
npm install
npm run dev
레이아웃에 들어가기 전에 children을 배워보자.(이거 알면 레이아웃 끝이다!)
272샘의 React6 글에서 React Element 구조가 대략 아래와 같다고 했다.
props도 있고, 그땐 의식하지 않았는뎅 children도 있다.
const element = {
type: 'h1',
props: {
className: 'greeting',
children:'안농,경민 기획자님 !'
}
};
그동안 우리가 만든 JSX 컴포넌트는 아래 처럼만 사용하였다.
<Container />
<Friend />
html태그들은 아래 처럼 열고(<div>) 닫는(</div>) 태그 형식에 그 사이에도 태그가 오는데...
<div>
<h1>경민 메롱</h1>
<h1>미누 더 메롱</h1>
</div>
div 태그가 부모(parent)고, h1 태그 2개가 자식들(children) 이다.
JSX도 같은 방식으로 사용 될 수 있다. 해보자!
index.css 는 아래 내용으로 덮어버리자.(그냥 7e샘 맘이다!)
/* 전체 적용 */
* {
box-sizing: border-box;
text-align: center;
}
h1 {
color:blue;
font-size: 3em;
}
/* body 태그 아니고 class임에 주의 */
.body {
border: 5px groove red;
height: 420px;
}
src 폴더에 아래 파일들을 만들자. (내용은 보자 마자 알수 있는 정도)
Child.jsx
function Child() {
return (
<div>
<h2>어린 시절</h2>
<img
width={200}
height={200}
/>
<h2>어른 시절</h2>
<img
width={200}
height={200}
/>
</div>
);
}
export default Child;
Parent.jsx
import PropsTypes from "prop-types";
Parent.propTypes = {
children: PropsTypes.node,
};
function Parent({ children }) {
return (
<div>
<h1>나 기획달인 경민이얌</h1>
{children}
</div>
);
}
export default Parent;
{ children } 은 props 안 children을 구조분해로 빼왔다.
누굴 가리키게 되는지 짐작이 올것이다. 그래동 관심을 가지고 결과 보자
결과를 눈으로 보기 위해 App.jsx를 아래 처럼 수정!!.
App.jsx
import Parent from "./Parent";
import Child from "./Child";
function App() {
return (
<div>
<Parent>
<Child />
</Parent>
</div>
);
}
export default App;
브라우져 결과는 아래와 같을 것이다.(아니면 e7e샘에게 연락하자!!!)
이제 결과를 보니 확실히 children이 누굴 가리키는지 느낌이 왔다..
children 알면 레이아웃은 거저다. 레이아웃 해보자.
원하는 목표는 아주 많이 사용되는 아래 모양 레이아웃이다.
Header, Side, Content, Footer를 각각 맹글고, 전체를 가진 Layout을 만들건데,
Content만 children으로 처리하는 방식으로 만들거다.
양만 많고, 내용은 별로 없으니, 복사/붙여넣기로 느낌만 받아도 좋다.
그럼 각각 맹글어 보자.
Header.css
.header {
border:10px groove pink;
height: 200px;
padding-top:20px;
}
Header.jsx
import "./Header.css";
function Header() {
return (
<div className="header">
<h1>요기가 Header </h1>
</div>
);
}
export default Header;
Side.css
.side {
display: inline-block;
width: 30%;
min-width: 200px;
height:100%;
border: 10px groove blue;
padding-top: 100px;
}
Side.jsx
import "./Side.css";
function Side() {
return (
<div className="side">
<h1>요기가 Side</h1>
</div>
);
}
export default Side;
Content.css
.content {
width: 70%;
min-width: 400px;
height: 100%;
display: inline-block;
border: 10px groove blueviolet;
vertical-align: top;
padding-top: 100px;
}
Content.jsx
import "./Content.css";
function Content() {
return (
<div className="content">
<h1>요기가 Content </h1>
</div>
);
}
export default Content;
Footer.css
.footer {
border: 10px groove black;
height: 200px;
padding-top:20px;
}
Footer.jsx
import "./Footer.css";
function Footer() {
return (
<div className="footer">
<h1>여긴 ©Footer 컴퍼니</h1>
</div>
);
}
export default Footer;
Header, Side,Content,Footer를 모두 포함할 Layout 컴포넌트
Layout.css
.layout {
border: 3px groove magenta;
min-width: 800px;
}
Layout.jsx (children 부분에 주목!)
import "./Layout.css";
import PropTypes from "prop-types";
import Header from "./Header";
import Side from "./Side";
import Footer from "./Footer";
Layout.propTypes = {
children: PropTypes.node,
};
function Layout({ children }) {
return (
<div className="layout">
<Header />
<div className="body">
<Side />
{children}
</div>
<Footer />
</div>
);
}
export default Layout;
Layout 결과를 확인하기 위해 App.jsx를 아래와 같이 수정하자.
App.jsx
import Layout from "./Layout";
import Content from "./Content";
function App() {
return (
<div>
<h2>경민이와 함께 하는 Layout</h2>
<Layout class="layout">
<Content />
</Layout>
</div>
);
}
export default App;
결과를 확인하면 원래 의도했던 결과가 보인다.
조금만 더 확인하고 가장.
Child.css 를 아래 내용으로 추가하자.
.child {
width: 70%;
min-width: 400px;
height: 100%;
display: inline-block;
border: 10px groove blueviolet;
vertical-align: top;
padding-top: 100px;
}
h2 {
display: inline-block;
}
사실 Content.css 를 복사한 거에, h2만 넣었당. 나래비로 나오게.
Child.jsx 도 위 css가 적용되도록 조금만 고쳐보장.
import "./Child.css"
function Child() {
return (
<div className="child">
<h2>어린 시절</h2>
<img
width={200}
height={200}
/>
<h2>어른 시절</h2>
<img
width={200}
height={200}
/>
</div>
);
}
export default Child;
App.jsx 에 Content 대신 Child가 들어가도록 수정!.
import Layout from "./Layout";
//import Content from "./Content";
import Child from "./Child";
function App() {
return (
<div>
<h2>경민이와 함께 하는 Layout</h2>
<Layout class="layout">
<Child />
</Layout>
</div>
);
}
export default App;
결과는 아래와 같을 것이다.
Layout에 자식을 주면 Header, Side, Footer는 그대로 이고
Content 자리 내용만 바뀐다.~~ 느낌이 왔길 기대해 본다...
어렵지 않은 내용이었으니, 여기서 1개만 더 확인하고 마무리 하자.
App.jsx의 return에서 전체를 감싸는 <div> </div>를 잠깐 지워보장.
import Layout from "./Layout";
//import Content from "./Content";
import Child from "./Child";
function App() {
return (
<h2>경민이와 함께 하는 Layout</h2>
<Layout class="layout">
<Child />
</Layout>
);
}
export default App;
빨간 파동줄이 생기고, 마우스를 올리면 아래 메세지가 보일것이다.
JSX expressions must have one parent element
JSX 식에는 부모 요소가 하나 있어야 합니다
JSX 표현식은 꼭 하나의 부모 요소를 가져야만 한다는 메세지다
문제는 div태그나 다른 태그를 부모로 넣어서 해결할 수 있지만,
실제 html문서에 부모로 아무 태그도 들어가게 하고 싶지 않을 때가 있다.
그럴 때는 아래 처럼 <React.Fragment>를 넣어도 되는 뎅.
App.jsx
import React from 'react'
import Layout from "./Layout";
//import Content from "./Content";
import Child from "./Child";
function App() {
return (
<React.Fragment>
<h2>경민이와 함께 하는 Layout</h2>
<Layout class="layout">
<Child />
</Layout>
</React.Fragment>
);
}
export default App;
길게 써야 하고, 괜히 어렵게 처리한 느낌이어서 보통 아래처럼 <> </>로 처리.
App.jsx
import Layout from "./Layout";
//import Content from "./Content";
import Child from "./Child";
function App() {
return (
<>
<h2>경민이와 함께 하는 Layout</h2>
<Layout class="layout">
<Child />
</Layout>
</>
);
}
export default App;
별거 아니지만,브라우져 개발자도구의 Elements 탭을 꼬옥 확인해 보기 바란다.
여기서 기억해야 할 한가지!, 별거 아니라 해서 그냥 넘어가면 안되요.. 안돼!!
꼬옥 전부 지우고, 본인이 어디까지 할 수 있는지?
다시 처음부터 해보아야만 한다!. 그렇지 않으면 착각과 망상에 빠진다!
출처 : https://e-7-e.tistory.com/258