[TIL] JSX / Props

·2023년 11월 1일
0

TIL

목록 보기
20/85
post-thumbnail

JSX

const element = <h1>Hello, world!</h1>;

이 문법은 문자열도 HTML도 아니다.
이 문법은 JSX 라고 부르며 자바스크립트의 문법 확장이다.(JavaScript + XML)
JSX 를 리액트와 함께 사용하여 UI가 실제로 어떻게 보일지 설명하는 것을 권장한다.

JSX에 표현식 포함하기

JSX 안에 자바스크립트 표현식을 중괄호 {} 로 묶어서 표현할 수 있다.

function formatName(user) {
  return user.firstName + ' ' + user.lastName;
}

const user = {
  firstName: 'Harper',
  lastName: 'Perez'
};

const element = (
  <h1>
    Hello, {formatName(user)}! // 이렇게
  </h1>
);

ReactDOM.render(
  element,
  document.getElementById('root')
);

JSX 속성 정의

속성에 따옴표를 이용해 문자열 리터럴을 정의할 수 있다.

const element = <div tabIndex="0"></div>;

속성에 중괄호를 이용해 자바스크립트 표현식을 포함시킬 수 있다.

const element = <img src={user.avatarUrl}></img>;
  • JSXHTML 보다는 JavaScript에 가깝기 때문에 ReactDOM은 HTML 속성 이름 대신 camelCase 속성 이름 컨벤션을 사용한다.
    • ex) JSX에서 classclassName 이 되며, tabindextabIndex 가 된다.

Props

props 는 컴포넌트끼리의 정보 교환 방식!
부모 컴포넌트가 자식 컴포넌트에게 물려준 데이터이다.

  1. props는 반드시 위에서 아래 방향으로 흐른다. 즉 [부모] -> [자식] 방향으로만 흐른다.
  2. props는 반드시 읽기 전용으로 취급하며, 변경하지 않는다.
import React from "react";

function User(props) { // 자식 컴포넌트가 props 받음 (Object형태)
  console.log(props); // 콘솔에 찍어보자
}

function App() { 
  const name = "hyewon";
  const age = 18;
  return (
    <div>
      <User name={name} age={age} /> // 부모 컴포넌트(App)가 자식 컴포넌트(User)에게 props 전달
    </div>
  );
}

export default App;

Props 추출

방법 1️⃣

props는 object 형태이기 때문에 {props.name} 과 같은 방식으로 꺼내서 사용할 수 있다.
(그러나.. 아무도 그렇게 잘 안씀 😃 후술할 '구조분해할당' 방식을 사용하자.)

import React from "react";

function User(props) {
  return <h1>{`제 이름은 ${props.name}이고 나이는 ${props.age}살입니다.😀`}</h1>;
}

function App() {
  const name = "hyewon";
  const age = 18;
  return (
    <div>
      <User name={name} age={age} />
    </div>
  );
}

export default App;

방법 2️⃣ (구조분해할당)

props는 object 형태이다. 그래서 우리는 '구조분해할당'을 이용할 수 있다.

구조분해할당?

  • 배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있게 하는 JavaScript 표현식
const obj = {
  name: "hyewon"
  age: 18
};
const {name, age} = obj;
console.log(name); // hyewon
console.log(age); // 18
import React from "react";

function User({ name, age }) {
  return <h1>{`제 이름은 ${name}이고 나이는 ${age}살입니다.😆`}</h1>;
}

function App() {
  const name = "hyewon";
  const age = 18;
  return (
    <div>
      <User name={name} age={age} />
    </div>
  );
}

export default App;

여러개의 props를 받는다면 {} 안에 여러개의 props를 그대로 써주면 각각의 개별 변수에 값을 담을 수 있다. 어떤 props를 받는지 명시적으로 드러나기때문에 방법 2️⃣ 를 더 많이 사용한다.

Props drilling

❗️ [부모] -> [자식] 컴포넌트간 데이터 전달이 이루어지는 방법이 props 이다.
[부모]->[자식]->[자식의 자식]->[자식의 자식의 자식] 이 데이터를 받기 위해서는 무려 3번이나 데이터를 내려주어야 한다. 이걸 바로 prop drilling, props가 아래로 뚫고 내려간다 라고 한다.
-> 우리는 이와 같은 패턴을 피해야 하므로 나중에 Redux와 같은 데이터 상태관리 툴을 사용할 수 있다.😀

Props Children

자식 컴포넌트로 정보를 전달하는 또 다른 방법이다.

import React from "react";

function User(props) {
  console.log(props); // 콘솔에 찍어보자!
}

function App() {
  return (
    <div>
      <User> 안녕하세요! </User>
    </div>
  );
}

export default App;

원래는 부모 컴포넌트에서 자식 컴포넌트로 props를 보낼 때 <User hello='안녕하세요' /> 이런 식으로 보냈다.
그러나 <User>안녕하세요</User> 이렇게 쓰면 children 이라는 이름의 props를 보낼 수 있다.
(이름은 children으로 정해져있다.)


children의 용도

<User children="안녕하세요" /> 이렇게 보내줘도 될 것 같지만..
children props는 주로 Layout 컴포넌트를 만들 때 사용된다.

Layout 컴포넌트 안에는 header 라는 컴포넌트가 있고, header 아래에 {props.children} 를 통해서 props를 받아 렌더링 하고 있다.
즉, Layout 컴포넌트가 쓰여지는 모든 곳에서 <Layout>…</Layout> 안에 있는 정보를 받아서 가져올 수 있는 것!

예시

// Layout.js
import React from "react";

function Layout(props) {
  return (
    <>
      <header style={{ border: "1px solid red", padding: "10px" }}>
        <div>이건 모든 페이지에서 보이는 헤더입니다.</div>
      </header>
      {props.children}
    </>
  );
}

export default Layout;
// App.js
import React from "react";
import Layout from "Layout";

function App() {
  return (
    <Layout>
      <div>여긴 App 컨텐츠가 들어갑니다</div> {/*children props*/}
    </Layout>
  );
}

export default App;
// index.js
import React from "react";
import App from "./App";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

이 코드를 통해, Layout에 있는 header가 보여지게 되고, “여긴 App의 컨텐츠가 들어갑니다.” 라는 문장이 Layout의 props로 전달된다.
결과적으로 우리는 header 컴포넌트를 Layout 컴포넌트에서 한번만 작성하면 여러 페이지에서 모두 보여지게 할 수 있다.

// About.js
import React from "react";
import Layout from "Layout";

function About() {
  return (
    <Layout>
      <div>여긴 About 컨텐츠가 들어갑니다</div> {/*children props*/}
    </Layout>
  );
}

export default About;
// index.js
import React from "react";
import About from "About";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <About />
  </React.StrictMode>
);

default Props

💡 defaultProps란, 부모 컴포넌트에서 props를 보내주지 않아도 설정될 초기 값이다.

import React from "react";

function Child({ name, age }) {
  return (
    <div>
      제 이름은 {name} 이고요 저는 {age} 살 입니다.
    </div>
  );
}
function App() {
  return <Child />;
}

export default App;

Child 컴포넌트 입장에서는 부모 컴포넌트에서 name을 props 정보를 받기 전까지는 name 이 없다.
그래서 자식 컴포넌트 입장에서는 name이 무엇인지 알 수 없다.
결과적으로 자식컴포넌트는 화면에 아무것도 표시해주지 못하게 된다.
그래서 부모 컴포넌트에서 props를 받기 전까지 임시로 사용할 수 있는 props를 설정할 수 있다.
이후에 부모 컴포넌트에서 props를 받게 되면 설정된 defaultProps는 사라지고 받은 props로 바뀌게 된다.

import React from "react";

function Child({ name, age }) {
  return (
    <div>
      제 이름은 {name} 이고요 저는 {age} 살 입니다.
    </div>
  );
}
// dafaultProps 설정
Child.defaultProps = {
  name: "기본이름",
  age: 0,
};

function App() {
  return <Child />; // 부모 컴포넌트에서 아무런 props를 보내지 않음.
}

export default App;

profile
느리더라도 조금씩, 꾸준히

0개의 댓글