React 적응기 - 5

shaqok·2020년 3월 20일
0

React

목록 보기
5/5

이전에 작성한 포스트와 책의 내용을 바탕으로 정리 및 추가를 하는 포스트이다.

JSX 문법

JSX 를 설명할 때 자바스크립트를 확장한 문법으로, React element 를 생성하고, 컴포넌트를 생성해 UI를 객체화할 수 있다고 작성했었는데,
이번에 JSX 가 Javascript XML 의 줄임말로 '자바스크립트에 XML을 추가한 확장형 문법' 이라는 정의도 알게 되었다.

즉, '리액트 엔진은 JSX의 XML 구조를 분석하여 자바스크립트 함수 코드로 변환해주는 것이다. 이것을 선언형 화면(Declarative View) 기술'이라고 한다.

컴포넌트

컴포넌트는 React element 를 리턴하는데, 자바스크립트의 함수와 비슷하다.

웹 사이트 화면에서는 반복적으로 사용되는 요소가 많은데, 컴포넌트는 각 요소를 작게 나누어 재사용성을 높이고 유지보수를 용이하게 만든다.

JSX element를 리턴하는 컴포넌트의 기초적인 구성 예시이다.

아래 App.js 를 보면 컴포넌트 HelloWorld 를 마치 html 태그처럼 추가하여 리턴하는 것을 볼 수 있다.

// HelloWorld.js
import React from 'react'

const HelloWorld = () => {
  return (
    <div>
      Hello World!
    </div>
  )
}

export default HelloWorld

// App.js
import React from 'react';
import HelloWorld from './HelloWorld';

function App() {
  return (
    <div className="App">
      <HelloWorld />
    </div>
  );
}

export default App;

컴포넌트를 구성하는 요소들은 아래와 같다.

Props(프로퍼티) - 상위 컴포넌트에서 하위 컴포넌트로 전달되는 read-only 데이터이다.

이 props에 관해 지켜야하는 규칙으로, '모든 React 컴포넌트는 자신의 props를 다룰 때 반드시 순수 함수처럼 동작해야 한다.' 는 점이 있는데, 순수 함수의 특징은 아래와 같다.

  • 같은 input은 같은 output을 리턴해야 한다.
  • 순수 함수에서는 파라미터 자체를 변경하면 안되고, read-only data로서만 이용하는 함수다. 리턴값은 오로지 파라미터에 의존한 값이어야 한다.
  • side effect(외부 상태의 변화)를 일으키지 않는다.

간단한 예시로

// 파라미터를 변경하며 값을 리턴하고 있기 때문에 순수 함수가 아니다.
const addNums = (firstNum, secondNum) => {
  firstNum = firstNum + secondNum;
  return firstNum;
}

// 두 파라미터의 합을 할당받는 result를 선언하여 리턴하므로 순수함수이다.
const addNums = (firstNum, secondNum) => {
  const result = firstNum + secondNum;
  return result;
}

App.js 와 HelloWorld.js 에 props 를 적용해보면,

// App.js
import React from 'react';
import HelloWorld from './HelloWorld';

function App() {
  return (
    <div className="App">
      // HelloWorld 컴포넌트에 전달할 data를 추가
      <HelloWorld name={'Daniel'} />
    </div>
  );
}

export default App;


// HelloWorld.js
import React from 'react'

// 인자로 props를 받아준 후,
const HelloWorld = (props) => {
  return (
    <div>
      // App.js에서 전달받은 데이터를 명시
      Hello World! Hi {props.name}
    </div>
  )
}

export default HelloWorld

props의 자료형(Data type)을 미리 지정을 해주면 리액트 엔진이 props의 값의 변화를 효율적으로 감지할 수 있고 디버깅에 효과적이다.

props의 자료형을 지정하는 방법은 리액트의 prop-types를 사용하면 된다.

// App.js
import React from 'react';
import HelloWorld from './HelloWorld';

function App() {
  return (
    <div className="App">
      <HelloWorld name={'Daniel'} />
    </div>
  );
}

export default App;


// HelloWorld.js
import React from 'react'
import PropTypes from 'prop-types';

const HelloWorld = ({ name }) => {
  return (
    <div>
      Hello World! Hi {name}
    </div>
  )
}

HelloWorld.propTypes = {
  name: PropTypes.string,
};

export default HelloWorld

그리고 특정 props가 꼭 전달되어야하는 props라면 isRequired를 추가해준다.

HelloWorld.propTypes = {
  name: PropTypes.string,isRequired,
};

리액트 공식문서에서 다양한 타입들을 확인할 수 있다.


State - 컴포넌트의 상태를 저장하고 변경할 수 있는 private한 데이터입니다.

'props를 전달받은 컴포넌트 내부에서는 직접적인 변경이 불가능하지만 컴포넌트의 state를 이용하면 위 규칙을 위반하지 않고 사용자 액션, 네트워크 응답 및 다른 요소에 대한 응답으로 시간에 따라 자신의 출력값을 변경할 수 있다.'

state를 변경할 때는 내장함수 setState를 이용해서 변경한다.

state 값을 직접 변경하면 안 되는 이유는 render() 함수로 화면을 그려주는 시점은 리액트 엔진이 정하기 때문이다. state 값을 직접 변경해도 render() 함수는 새로 호출되지 않는다.
하지만 setState() 함수로 state를 변경하면 리액트 엔진이 자동으로 render() 함수를 호출하면서 화면에 변경된 state를 새로 출력한다.

import React from 'react';

class Clock extends React.Component {
  constructor(props) {
    super(props);
    // state 객체에 키: 값 으로 새로운 데이터를 선언한다.
    this.state = {
      date: new Date()
    };
  }
  
  // setState 메소드를 이용해 state 안의 원하는 값을 갱신한다.
  tick() {
    this.setState({
      date: new Date()
    });
  }
  
  // 버튼이 클릭되면 1초마다 this.state.date를 갱신한다.
  startClock() {
    setInterval(() => this.tick(), 1000);
  }
  
  render() {
    return (
      <div>
        <button
          // onClick 이벤트에 this.startClock을 실행한다.
          onClick={() => this.startClock()}
        >start</button>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

export default Clock;

setStaterender 메소드 안에서 사용하면 안되는 이유는, state가 변경되면 '리액트 엔진이 자동으로 render 메소드를 호출하면서 변경된 state를 출력하게 되므로' setStaterender 메소드 안에서 사용하면 무한루프에 빠지게 된다.

참조

https://ko.reactjs.org/docs/components-and-props.html

0개의 댓글