상세 컨텐츠

본문 제목

React(리액트) 티키타카 10 (레이아웃, children )

React

by e7e 2024. 10. 6. 19:22

본문

2024.10.02 - [React] - React(리액트) 티키타카 9 ( Props 구조 분해 )

까지 읽었다면 , 웹 프로그램을 해본 경험이 있는 사람은 조금이나마 

느끼미란 게 분명 있었을 거당. (없다면 당신은 프론트 경험이 없는 거나 마찬가징..)

 

오늘은 좀 쉬운 걸  해보려 한당. 레이아웃이당.

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을 배워보장.(요거 알면 레이아웃 끄시당!)

티키타카 6 글에서 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 는 아래 내용으로 더퍼버리장.(그냥 내 맘이당!)

/* 전체 적용 */
* {
  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}
        src="https://api.dicebear.com/9.x/adventurer/svg?seed=merong"
      />
      <h2>어른 시절</h2>
      <img
        width={200}
        height={200}
        src="https://api.dicebear.com/9.x/adventurer/svg?seed=Jude"
      />
    </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;

 

브라우져 결과는 아래와 같을 거시당.(아니라공 내게 연락하지 마랑!)

이제 결과를 보니 확실히 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>여긴 &copy;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}
          src="https://api.dicebear.com/9.x/adventurer/svg?seed=merong"
        />
        <h2>어른 시절</h2>
        <img
          width={200}
          height={200}
          src="https://api.dicebear.com/9.x/adventurer/svg?seed=Jude"
        />
      </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 표현식은 꼭 하나의 부모 요소를 가져야만 한다는 메세지당.

 

문제는 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://www.youtube.com/watch?v=YEA1ROHi0Eg

 

관련글 더보기