본문 바로가기
Front-end/React\RN

React with Redux, Next.js, TypeScript - 1 컴포넌트, JSX, 속성, 상태

by javapp 자바앱 2024. 3. 6.
728x90

 

 

Udemy 강의 "React 완벽 가이드 with Redux, Next.js, TypeScript" 를 보고 정리하였습니다.

 

 

컴포넌트, JSX, 속성, 상태

 

 

기본개념

JSX

JavaScript Syntax eXtension

-> but 브라우저에 사용 불가능합니다.

그래서 브라우저에 도달하기 전에 개발 서버에서 변환됩니다.

 

 

리액트에서의 컴포넌트

컴포넌트 = 자바스크립트 함수

- 컴포넌트의 첫글자는 대문자, PascalCase(MyHeader)

커스텀 컴포넌트는 실제로 렌더링된 DOM에 나타나지 않습니다.

 

 

 

 

동적 값 출력

외부에 정의된 값들을 가져옵니다.

import { CORE_CONCEPTS } from "./data.js";

 

import componentsImg from "./assets/components.png";
import propsImg from "./assets/config.png";
import jsxImg from "./assets/jsx-ui.png";
import stateImg from "./assets/state-mgmt.png";

export const CORE_CONCEPTS = [
  {
    image: componentsImg,
    title: "Components",
    description:
      "The core UI building block - compose the user interface by combining multiple components."
  },
  {
    image: jsxImg,
    title: "JSX",
    description:
      "Return (potentially dynamic) HTML(ish) code to define the actual markup that will be rendered."
  },
  {
    image: propsImg,
    title: "Props",
    description:
      "Make components configurable (and therefore reusable) by passing input data to them."
  },
  {
    image: stateImg,
    title: "State",
    description:
      "React-managed data which, when changed, causes the component to re-render & the UI to update."
  }
];

 

 

 

해당 데이터들을 출력할 컴포넌트 작성합니다.

props 를 통해 사용가능합니다.

 

function CoreConcept({ image, title, description }) {
  return (
    <li>
      <img src={image} alt={title} />
      <h3>{title}</h3>
      <p>{description}</p>
    </li>
  );
}

여기서는 자바스크립트의 구조분해를 사용합니다.

 

 

function App() {
  return (
    <div>
      <Header />
      <main>
        <section id="core-concepts">
          <h2>Time to get started!</h2>
          <ul>
            <CoreConcept
              title={CORE_CONCEPTS[0].title} // props
              description={CORE_CONCEPTS[0].description}
              image={CORE_CONCEPTS[0].image}
            />
            <CoreConcept {...CORE_CONCEPTS[1]} />
          </ul>
        </section>
      </main>
    </div>
  );
}

 

 

스프레드 연산자를 통해 데이터를 가져올 수 있습니다.

<CoreConcept {...CORE_CONCEPTS[1]} />

 

 


 

 

프로젝트 구조활용

 

App.jsx

import { CORE_CONCEPTS } from "./data.js";
import Header from "./components/Header";
import CoreConcept from "./components/CoreConcept";

function App() {
  return (
    <div>
      <Header />
      <main>
        <section id="core-concepts">
          <h2>Time to get started!</h2>
          <ul>
            <CoreConcept
              title={CORE_CONCEPTS[0].title} // props
              description={CORE_CONCEPTS[0].description}
              image={CORE_CONCEPTS[0].image}
            />
            <CoreConcept {...CORE_CONCEPTS[1]} />
          </ul>
        </section>
      </main>
    </div>
  );
}

export default App;

 

 

Header, CoreConcept 를 컴포넌트 단위로 나누어 사용합니다.

 

 

 

 

 

Header.jsx

import reactImg from "../assets/react-core-concepts.png";

const reactDescriptions = ["Fundamental", "Crucial", "Core"];

function genRandomInt(max) {
  return Math.floor(Math.random() * (max + 1));
}

export default function Header() {
  const description = reactDescriptions[genRandomInt(2)];

  return (
    <header>
      <img src={reactImg} alt="Stylized atom" />
      <h1>React Essentials</h1>
      <p>
        {description} Fundamental React concepts you will need for almost any
        app you are going to build!
      </p>
    </header>
  );
}

 

export default 선언을 하여 외부에서 사용할 수 있습니다.

 

 

 

CoreConcept.jsx

export default function CoreConcept(props) {
  return (
    <li>
      <img src={props.image} alt=".." />
      <h3>{props.title}</h3>
      <p>{props.description}</p>
    </li>
  );
}

 

 

 

 

props

 

 

라벨 label 으로 사용

 

app.jsx

<TabButton label="컴포넌트"/>

 

 

TabButton

export default function TabButton({ label }) {
  return (
    <li>
      <button>{label}</button>
    </li>
  );
}

 

 

 

 

이벤트

  function handleSelect() {
    console.log("select");
  }
 
...
 
<TabButton onSelect={handleSelect}>메뉴1</TabButton>

 

구조분해 할당 사용 

export default function TabButton({ children, onSelect }) {
  return (
    <li>
      <button onClick={onSelect}>{children}</button>
    </li>
  );
}

 

 

 

 


 

 

조건부 렌더링 

 

이러한 탭이 있을 때

탭을 누르기 전에는 

탭을 눌러달라는 문구를 띄우고 싶을 때

 

 

 

 

  {!useSelectedTopic && <p> 주제를 선택해주세요 </p>}
  {useSelectedTopic && (
    <div id="tab-content">
      <h3>{EXAMPLES[useSelectedTopic].title}</h3>
      <p>{EXAMPLES[useSelectedTopic].description}</p>
      <pre>
        <code>{EXAMPLES[useSelectedTopic].code}</code>
      </pre>
    </div>
  )}

 

 

 

함수를 통한 방법

  let tabContent = <p> 주제를 선택해주세요 </p>;
  if (useSelectedTopic) {
    tabContent = (
      <div id="tab-content">
        <h3>{EXAMPLES[useSelectedTopic].title}</h3>
        <p>{EXAMPLES[useSelectedTopic].description}</p>
        <pre>
          <code>{EXAMPLES[useSelectedTopic].code}</code>
        </pre>
      </div>
    );
  }
  
  
  
  ..
  
  
  {tabContent}

 

JSX가 더 깔끔해지고 관리하기 더욱 용이해진다.

 

 

 


 

 

CSS 동적 스타일링

            <TabButton
              isSelected={useSelectedTopic === "components"}
              onSelect={() => handleSelect("components")}
            >
              components
            </TabButton>
            <TabButton
              isSelected={useSelectedTopic === "jsx"}
              onSelect={() => handleSelect("jsx")}
            >
              JSX
            </TabButton>
            <TabButton
              isSelected={useSelectedTopic === "props"}
              onSelect={() => handleSelect("props")}
            >
              props
            </TabButton>
            <TabButton
              isSelected={useSelectedTopic === "state"}
              onSelect={() => handleSelect("state")}
            >
              state
            </TabButton>

버튼 클릭시 isSelected에 값을 담아서 보낸다.

 

 

export default function TabButton({ children, onSelect, isSelected }) {
  return (
    <li>
      <button className={isSelected ? "active" : undefined} onClick={onSelect}>
        {children}
      </button>
    </li>
  );
}

isSelected 값이 있으면 active가 활성화 되어서 css 가 적용되게 함

 

 

 

내장 map 을 사용하여 목록 데이터를 동적으로 출력

            {/* <CoreConcept
              title={CORE_CONCEPTS[0].title} // props
              description={CORE_CONCEPTS[0].description}
              image={CORE_CONCEPTS[0].image}
            />
            <CoreConcept {...CORE_CONCEPTS[1]} /> */}

            {CORE_CONCEPTS.map((conceptItem) => (
              <CoreConcept key={conceptItem.title} {...conceptItem} />
            ))}

 

 

댓글