JSX In Depth[React]

SnowCat·2023년 2월 23일
0
post-thumbnail
  • JSX -> React.createElement(component, props, ...children)으로 변환되는 문법적 설탕
//jsx 코드
<MyButton color="blue" shadowSize={2}>
  Click Me
</MyButton>
<div className="sidebar" />

// 컴파일시 다음과 같이 바뀜
React.createElement(
  MyButton,
  {color: 'blue', shadowSize: 2},
  'Click Me'
)
React.createElement(
  'div',
  {className: 'sidebar'}
)

React Element의 타입 지정

  • JSX 태그의 첫 부분은 React Element의 타입 결정
  • JSX 태그는 같은 이름을 가진 변수들을 직접 참조함 -> 같은 스코프 내에 참조할 컴포넌트가 있어야 함
  • JSX가 React.createElement를 호출하는 코드로 컴파일 되기 때문에 리액트 라이브러리 역시 JSX 코드와 같은 스코프내에 존재해야 함
    html의 script 태그로 리액트를 불러오면 전역변수로 존재하기 때문에 불러올 필요가 없음
import React from 'react';
import CustomButton from './CustomButton';

function WarningButton() {
  return <CustomButton color="red" />;
  // = return React.createElement(CustomButton, {color: 'red'}, null);
}
  • JSX 타입 내에서 점 표기법을 통해 특정한 컴포넌트를 지정할 수 있음
import React from 'react';

const MyComponents = {
  DatePicker: function DatePicker(props) {
    return <div>Imagine a {props.color} datepicker here.</div>;
    // return React.createElement("div", null, `Imagine a {props.color} datepicker here.`)
  }
}

function BlueDatePicker() {
  return <MyComponents.DatePicker color="blue" />;
  // return React.createElement("div", {color: "blue"}, null)
}
  • 소문자로 시작하는 컴포넌트는 내장 컴포넌트로 간주하기 때문에 컴포넌트를 작성할때는 대문자로 시작하는 이름을 지어야 함
import React from 'react';

function Hello(props) {
  return <div>Hello {props.toWhat}</div>;
}

function HelloWorld() {
  return <Hello toWhat="World" />;
}
  • React Element 타입에 일반적인 표현식을 사용할 수 없기 때문에 다른 변수에 먼저 값을 지정한 다음 사용해야 함
import React from 'react';
import { PhotoStory, VideoStory } from './stories';

const components = {
  photo: PhotoStory,
  video: VideoStory
};

function Story(props) {
  const SpecificStory = components[props.storyType];
  return <SpecificStory story={props.story} />;
}

JSX 안에서의 prop 사용

  • 자바스크립트 표현을 {} 안에 넣어서 JSX 안에서 prop으로 사용 가능
  • if, for문 등은 표현식이 아니기 때문에 JSX안에서 사용 불가능
  • JSX 밖의 코드 주변에서 값을 가져와야 함
function NumberDescriber(props) {
  let description;
  if (props.number % 2 == 0) {
    description = <strong>even</strong>;
  } else {
    description = <i>odd</i>;
  }
  return <div>{props.number} is an {description} number</div>;
}
  • 문자열 리터럴은 prop으로 넘길 수 있음
<MyComponent message="&lt;3" />

<MyComponent message={'<3'} />
  • prop에 어떠한 값도 넘기지 않으면 기본값은 true로 설정됨
<MyTextBox autocomplete />

<MyTextBox autocomplete={true} />
  • prop에 넘길 객체를 이미 정의해 두었다면 spread 연산자로 전개 가능
function App1() {
  return <Greeting firstName="Ben" lastName="Hector" />;
}

function App2() {
  const props = {firstName: 'Ben', lastName: 'Hector'};
  return <Greeting {...props} />;
}

const Button = props => {
  const { kind, ...other } = props;
  const className = kind === "primary" ? "PrimaryButton" : "SecondaryButton";
  return <button className={className} {...other} />;
};

const App = () => {
  return (
    <div>
      <Button kind="primary" onClick={() => console.log("clicked!")}>
        Hello World!
      </Button>
    </div>
  );

JSX에서 자식 다루기

  • 여는 태그와 닫는 태그가 있는 JSX에서 두 태그 사이 내용은 props.children이라는 특수한 prop으로 넘겨짐
  • 문자열이 들어오게 되면 props.children은 문자열이 됨
<MyComponent>Hello world!</MyComponent>

// HTML 이스케이프 처리가 되지 않음으로 특수문자 사용에 주의
<div>This is valid HTML &amp; JSX at the same time.</div>

// 태그 앞뒤의 공백은 제거되고, 개행문자는 하나의 문자로 대체됨
// 따라서 모두 Hello world!와 동일
<div>
  Hello
  World
</div>

<div>

  Hello World
</div>
  • 자식 요소로 다른 JSX 요소가 들어올수도 있음
<div>
  Here is a list:
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
  </ul>
</div>
  • 자식 요소로 자바스크립트 표현식도 들어올 수 있음
function Item(props) {
  return <li>{props.message}</li>;
}

function TodoList() {
  const todos = ['finish doc', 'submit pr', 'nag dan to review'];
  return (
    <ul>
      {todos.map((message) => <Item key={message} message={message} />)}
    </ul>
  );
}

// props.children값은 어느 값이든 전달될 수 있음
// 컴포넌트에 미리 정의해둔 경우 리액트가 이해할 수 있다면 값을 반환하는 함수 역시 사용 가능
function Repeat(props) {
  let items = [];
  for (let i = 0; i < props.numTimes; i++) {
    items.push(props.children(i));
  }
  return <div>{items}</div>;
}

function ListOfTenThings() {
  return (
    <Repeat numTimes={10}>
      {(index) => <div key={index}>This is item {index} in the list</div>}
    </Repeat>
  );
}
  • null, undefined, false, true는 child로 들어올 수 있지만 렌더링 되지는 않음
// 아래 5개의 태그는 전부 같은 값 출력
<div />

<div></div>

<div>{false}</div>

<div>{null}</div>

<div>{undefined}</div>

<div>{true}</div>

// 조건부 렌더링에서의 활용
<div>
  {showHeader && <Header />}
  <Content />
</div>

// 0, ""처럼 falsy한 값들은 리액트가 렌더링함에 주의
<div>
  {props.messages.length &&
    <MessageList messages={props.messages} />
  }
</div>
profile
냐아아아아아아아아앙

0개의 댓글