[Day 41] React Advance(JSX more, Static Type Check, Ref, Board Exercise)

앞으로의 Curriculum

  1. VS CODE 에서의 리액트 코딩
    • create-react-app
  2. CSS 구조적 코딩 (CSS의 스코프를 만들어주는)
    • BEM -> CSS 모듈
  3. HTML5 History API + React Router
    • SPA에 Routing을 잡아주고 각각의 페이지로 동작하도록
  4. 상태와 표현의 분리
    • Container Component (상태만 관리)
    • Presentational Component (그리기만)
    • 테스트를 위한 도구인 Story Board
  5. React에서 SEO 관리를 위한 기술
    • SSR (Server Side Rendering)
    • Next.js

React Advance

JSX 더 알아보기

React 엘리먼트의 타입 지정하기

JSX 태그의 첫 부분은 React 엘리먼트의 타입을 결정한다.

대문자로 시작하는 타입은 해당 JSX 태그가 React 컴포넌트임을 가리킨다.

<MyButton color="blue" shadowSize={2}>
  Click Me
</MyButton>

위와 같이 컴포넌트를 불러오는 JSX 표현을 사용하려면 해당 컴포넌트가 반드시 스코프 내에 존재해야 한다.

React가 스코프 안에 있어야 한다.

JSX는 React.createElement를 호출하는 코드로 컴파일 되기 때문에 React 라이브러리가 JSX 코드의 스코프 안에 항상 있어야만 한다.

import React from 'react';
import CustomButton from './CustomButton';

function WarningButton() {
  // return React.createElement(CustomButton, {color: 'red'}, null);
  return <CustomButton color="red" />;
}

JSX 타입을 위한 점 표기법

import React from 'react';

const MyComponents = {
  DatePicker: function DatePicker(props) {
    return <div>Imagine a {props.color} datepicker here.</div>;
  }
}

function BlueDatePicker() {
  return <MyComponents.DatePicker color="blue" />;
}

객체의 속성 값으로 컴포넌트가 올 수 있다.

사용자 정의 컴포넌트는 대문자로 시작해야 한다.

엘리먼트 타입이 소문자로 시작할 경우, DOM의 내장 컴포넌트(태그)를 의미하며 문자열의 형태로 컴파일 되면서 React.createElement로 전달된다.

대문자로 시작하는 타입은 하나의 변수(컴포넌트)로 React.createElement 에 인수로 전달된다.

실행 중에 타입 선택하기

prop을 가지고 컴포넌트를 선택해서 센더링해야 하는 경우

import React from 'react';
import { PhotoStory, VideoStory } from './stories';

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

function Story(props) {
  // 올바른 사용법입니다. 대문자로 시작하는 변수는 JSX 타입이 될 수 있습니다.
  const SpecificStory = components[props.storyType];
  return <SpecificStory story={props.story} />;
}

JSX 안에서 prop 사용하기

Props의 기본값은 “True”

<MyTextBox autocomplete />

<MyTextBox autocomplete={true} />

속성 펼치기

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를 자식으로 사용하기

<MyContainer>
  <MyFirstComponent />
  <MySecondComponent />
</MyContainer>

React 컴포넌트는 엘리먼트로 이루어진 배열을 반환할 수도 있다.

render() {
  // 별도의 엘리먼트로 감싸줄 필요가 없습니다!
  return [
    // 키를 잊지 마세요 :)
    <li key="A">First item</li>,
    <li key="B">Second item</li>,
    <li key="C">Third item</li>,
  ];
}

함수를 자식으로 사용하기

// Calls the children callback numTimes to produce a repeated component
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>
  );
}
  • 여는 태그와 닫는 태그 사이의 문자열 또는 {} 안의 표현식props.children 으로 컴파일 된다.

진리값, null, undefined는 무시된다.

true, false, null, undefined 는 유효한 자식이다. 다만, 렌더링되지는 않는다.

이러한 성질을 이용해 React 엘리먼트를 조건부로 렌더링할 수 있다.

<div>
  {showHeader && <Header />}
  <Content />
</div>

(주의!) React는 false는 렌더링하지 않지만 falsy는 렌더링한다.

0 이나 NaN 같은 falsy 값들은 렌더링 된다.

// props.messages.length가 0이라면 렌더링 된다.
<div>
  {props.messages.length &&
    <MessageList messages={props.messages} />
  }
</div>

(활용) 렌더링되지 않는 true, false, null, undefined를 렌더링하고 싶다면 문자열로 변환한 뒤 사용하면 된다.

<div>
  My JavaScript variable is {String(myVariable)}.
</div>

정적 타입 체크

정적 타이핑 vs 동적 타이핑

정적 타이핑 언어

코드를 실행하기 전 컴파일 과정에서 타입을 검사한다. (ex. Java, C, C++, C#, Swift, Kotlin …)

실행 전에도 타입 관련 버그를 발견할 수 있다.

동적 타이핑 언어

실행 시간에 타입을 검사한다. (ex. JavaScript, Python, Ruby …)

타입에러는 코드를 실행시킬 때 발생한다.

실행 전에는 타입 관련 버그를 발견하기 어렵다는 단점이 있다.

이러한 문제를 해결하기 위해 자바스크립트에 컴파일 과정 중 타입 체크 기능을 추가한 확장 언어가 존재한다. (ex. TypeScript, Flow …)

내가 선언한 변수들의 상태를 관리할 수 있다. (코드를 읽기가 쉬워진다.)

Ref와 DOM

Ref는 render() 메소드에서 생성된 DOM 노드 혹은 React 엘리먼트 객체에 접근할 수 있도록 해준다.

Ref를 사용해야 하는 때

  1. 포커스, 텍스트 선택영역, 혹은 미디어의 재생을 관리할 때 (DOM API의 메소드를 사용할 수 밖에 없을 때)
  2. 명령형 애니메이션을 발동시킬 때
  3. 서드파티 DOM 라이브러리를 통합할 때 (DOM 객체에 직접 작용하는 라이브러리를 사용해야 할 때)
  4. DOM 객체를 가리키고 싶을 때

Ref 생성하기

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
  render() {
    return <div ref={this.myRef} />;
  }
}

Ref 사용하기

React 엘리먼트에 ref가 넘겨지면 current 속성을 통해 해당 노드에 접근할 수 있다.

const node = this.myRef.current;

(중요!) ref의 값은 노드의 유형에 따라 달라진다.

  • HTML 엘리먼트에 ref 어트리뷰트가 사용되면 ref의 current 속성은 DOM 엘리먼트 객체를 가리킨다.
  • 클래스 컴포넌트에 ref 어트리뷰트가 사용되면 ref의 current 속성은 해당 컴포넌트로부터 생성된 인스턴스(public instance)를 가리킨다.

함수형 컴포넌트는 인스턴스를 가질 수 없기 때문에 ref 어트리뷰트를 사용할 수 없다.

게시판 실습

create-react-app

package bundler 도구인 Webpack과 JS Compiler인 Babel 을 미리 셋팅해놓은 프로젝트를 만들어주는 npm package

// npx는 npm에서 패키지를 받아서 바로 실행시키는 명령어
npx create-react-app fds-bbs
cd fds-bbs
npm start

Folder Structure

my-app/
  README.md
  node_modules/
  package.json
  public/
    index.html
    favicon.ico
  src/
    App.css
    App.js
    App.test.js
    index.css
    index.js
    logo.svg

public folder 내부의 파일은 build 과정을 거치지 않고 사용자에게 전달된다.

src folder 내부의 파일은 build 과정(transpiling)을 거친 후 사용자에게 전달된다.

Supported Browsers and Features

지원되는 브라우저 및 기능 확인

IE 9, 10, 11 에서는 polyfill 을 통해 사용할 수 있다.

IE8 이하는 지원하지 않는다.

Life-Cycle

componentDidMount() {}

componentDidMount 함수가 비동기함수여도 데이터를 다 받아온 뒤에 componentDidMount 함수가 실행되는 것은 아니다.

해당 컴포넌트가 그려질 때 무조건 componentDidMount 함수가 실행되면서 한 번 그려지고, 그 안에 setState()가 있다면 상태를 바꾸고 또 다시 그린다.

태그: ,

업데이트:

댓글남기기