3.1 클래스형 컴포넌트

클래스형 컴포넌트 특징

  • state 기능 및 라이프사이클 기능을 사용할 수 있음
  • 임의 메서드를 정의할 수 있음.
  • render 함수가 꼭 있어야 함. 

함수형 컴포넌트 특징

  • 클래스형 컴포넌트보다 선언하기 편함
  • 메모리 자원을 클래스형 컴포넌트보다 덜 사용함.
  • 빌드 후 배포할 때도 클래스형 컴포넌트와 비교했을 때 결과물의 크기가 더 작음.
  • state 및 라이프사이클 API를, Hooks라는 기능을 통해 간접 구현( v16.8)
  • 리액트 공식 매뉴얼에서 함수형 컴포넌트와 Hooks를 사용하도록 권장.
1.함수형
import React from "react";
import './App.css';

function App() {
  const name = '리액트';
  return <div className="react">{name}</div>
}

export default App;

2.클래스형
import React, {Component} from "react";
import './App.css';

class App extends Component {
  render() {
    const name = 'react';
    return <div className="react">{name}</div>
  }
}

export default App;

3.2 첫 컴포넌트 생성

//화살표 함수로 함수형 컴포넌트 구현
import React from "react";

const MyComponent = () => {
    return <div>화살표형 함수로 컴포넌트 구현</div>;
};

export default MyComponent;

일반 함수 vs 화살표형 함수

  • 화살표형 함수가 일반 함수를 완전히 대체할 수 있을까? (X) 둘의 용도가 다르므로 완전 대체는 불가능함.
    (화살표 함수는 주로 함수를 파라미터로 전달할 때 유용)
  • 함수 안에서 this를 호출했을 때 일반 함수는 자신이 종속된 객체를 가리키며, 화살표 함수는 자신이 종속된 인스턴스를 가리킴.
  • 화살표 함수는 값을 연산하여 바로 반환해야 할 때 사용하면 가독성을 높일 수 있음.
    (따로 { } 를 열어주지 않으면 연산한 값을 그대로 반환) 
    ex> function twice(value) {return value*2};  ===> const triple = (value) => value*3;
1.일반 함수에서의 this
function BlackDog() {
    this.name = '흰둥이';
    return {
        name: '검둥이',
        bark: function () {
            console.log(this.name + ': 멍멍!');
        }
    }
}

const blackDog = new BlackDog();
blackDog.bark(); //검둥이: 멍멍!


2.화살표 함수에서의 this
function WhiteDog() {
    this.name = '흰둥이';
    return {
        name: '검둥이',
        bark: () => {
            console.log(this.name + ': 멍멍!');
        }
    }
}

const whiteDow = new WhiteDog();
whiteDow.bark(); //흰둥이: 멍멍!

3.3 props

3.3.1 JSX 내부에서 props 랜더링

import React from "react";

const MyComponent = props => {
    return <div>안녕하세요, 제 이름은 {props.name} 입니다.</div>;
};

export default MyComponent

3.3.2 컴포넌트를 사용할 때 props값 지정하기

import React from 'react';
import MyComponent from "./MyComponent";

const App = () => {
    return <MyComponent name="React"/>
}

export default App;

3.3.3 props 기본값 설정 : defaultProps

import React from "react";

const MyComponent = props => {
    return <div>안녕하세요, 제 이름은 {props.name} 입니다.</div>;
};

MyComponent.defaultProps = {
    name: '기본 이름'
}

export default MyComponent

3.3.4 태그 사이의 내용을 보여주는 children

1.children 전달
import React from 'react';
import MyComponent from "./MyComponent";

const App = () => {
    return <MyComponent>리액트</MyComponent>
}

export default App;


2.porps로 받은 children 출력
import React from "react";

const MyComponent = props => {
    return (
        <div>
            안녕하세요, 제 이름은 {props.name} 입니다.<br/>
            children 값은 {props.children}
        </div>);
};

MyComponent.defaultProps = {
    name: '기본 이름'
}

export default MyComponent

3.3.5 비구조화 할당 문법을 통해 props 내부 값 추출하기

import React from "react";

const MyComponent = props => {
    const {name, children} = props;
    return (
        <div>
            안녕하세요, 제 이름은 {name} 입니다.<br/>
            children 값은 {children}
        </div>);
};


export default MyComponent

3.3.6 propTypes를 통한 props 검증

컴포넌트에서 설정한 props가 propsTypes에서 지정한 형태와 일치하지 않는다면 브라우저 개발자 도구의 console 탭에 경고 메시지 출력됨.

import React from "react";
import PropTypes from 'prop-types';

const MyComponent = props => {
...
};

MyComponent.propTypes = {
    name : PropTypes.string,
    favoriteNumber : PropTypes.number.isRequired
}

export default MyComponent

3.3.7 클래스형 컴포넌트에서 props 사용하기

Class형 컴포넌트는 render함수 내부에서 this.props를 조회. defaultProps, propTypes는 함수형 컴포넌트와 같은 방식으로 하거나 class 내부에서 지정

import React, {Component} from "react";
import PropTypes from 'prop-types';


class MyComponent extends Component {
    static defaultProps = {
        name: '기본 이름'
    }

    static propTypes = {
        name: PropTypes.string
    }

    render() {
        const {name, favoriteNumber, children} = this.props; //비구조화 할당
        return (
            <div>
                안녕하세요, 제 이름은 {name} 입니다.<br/>
                children 값은 {children}
                <br/>
                제가 좋아하는 숫자는 {favoriteNumber} 입니다.
            </div>
        );
    }
}

export default MyComponent

3.4 state

3.4.1 클래스형 컴포넌트의 state

state를 설정할 때 constructor 메서드(생성자)를 사용함.
constructor를 작성할 때는 반드시 super(props)를 호출해야 함.
(클래스형 컴포넌트가 상속하고 있는 리액트의 Component 클래스가 지닌 생성자 함수를 호출해줌.)

1.
import React, {Component} from "react";

class Counter extends Component {
    constructor(props) {
        super(props);
        //state의 초깃값 설정하기
        this.state = {
            number: 0,
            fixedNumber: 0
        };
    }

    render() {
        const {number, fixedNumber} = this.state;
        return (
            <div>
                <h1>{number}</h1>
                <h2>바뀌지 않는 값  : {fixedNumber}</h2>
                <button onClick={() => {
                    this.setState({number: number + 1});
                    //setState함수는 인자로 전달된 객체 안에 들어 있는 값만 바꾸어 줌.
                }}>
                    +1
                </button>
            </div>
        );
    }
}

export default Counter;


2.constructor 메소드를 선언하지 않고, state초깃값 설정
import React, {Component} from "react";

class Counter extends Component {
    state = {
        number: 0,
        fixedNumber: 0
    };

    render() {
        const {number, fixedNumber} = this.state;
        return (
            <div>
                <h1>{number}</h1>
                <h2>바뀌지 않는 값 : {fixedNumber}</h2>
                <button onClick={() => {
                    this.setState({number: number + 1});
                    //setState함수는 인자로 전달된 객체 안에 들어 있는 값만 바꾸어 줌.
                }}>
                    +1
                </button>
            </div>
        );
    }
}

export default Counter;


3.this.setState에 객체 대신 함수 인자 전달

<button onClick={() => {
    this.setState(prevState => {
        return {number: prevState.number + 1}
    });
    // { } 생략해서 함수에서 값 바로 반환
    this.setState(prevState => ({number: prevState.number + 1}));
}}>
    +1
</button>

4.this.setState가 끝난 후 특정 작업 실행하기
<button onClick={() => {
    this.setState({number: number + 1}, () => {
        console.log('방금 setState가 호출되었습니다.');
        console.log(this.state);
    });
    //setState함수는 인자로 전달된 객체 안에 들어 있는 값만 바꾸어 줌.
}}>
    +1
</button>

3.4.2 함수형 컴포넌트에서 useState 사용하기

리액트 16.8이후 userState라는 함수를 사용하여 함수형 컴포넌트에서도 statef를 사용할 수 있게됨.
클래스형 컴포넌트에서의 state 초깃값은 객체 형태를 넣어줘야 하지만, useState는 값의 형태가 자유로움.
함수를 호출하면 배열이 반환됨. 첫 번째 원소는 현재 상태, 두 번째 원소는 상태를 바꿔주는 함수(세터).
배열 비구조화 할당을 통해 이름을 자유롭게 정해 줄 수 있음.

import React, {useState} from "react";

const Say = () => {
    const [message, setMessage] = useState('');
    const onClickEnter = () => setMessage('안녕하세요!');
    const onClickLeave = () => setMessage('안녕히 가세요!');
    return (
        <div>
            <button onClick={onClickEnter}>입장</button>
            <button onClick={onClickLeave}>퇴장</button>
            <h1>{message}</h1>
        </div>
    );
}

export default Say;

3.5 state를 사용할 때 주의 사항

  • state값을 바꾸어야 할 때 setState혹은 useState를 통해 전달받은 세터 함수를 사용해야 함.
  • 배열이나 객체는 사본을 만들고 그 사본에 값을 업데이트한 후, 그 사본의 상태를 setState혹은 세터 함수를 통해 업데이트해야 함.
//객체 다루기
const object = {a: 1, b: 2, c: 3};
const newtObject = {...object, b: 2}; //사본을 만들어서 b값만 덮어 쓰기


//배열 다루기
const array = [
    {id: 1, value: true},
    {id: 2, value: true},
    {id: 3, value: true},
];
let nextArray = array.concat({id: 4});
nextArray.filter(item => item.id !== 2);
nextArray.map(item => (item.id === 1) ? {...item, value: false}, item);

 

'개발 도서 > 리액트를 다루는 기술(개정판)' 카테고리의 다른 글

5장 ref:DOM에 이름 달기  (0) 2020.05.23
4장 이벤트 핸들링  (0) 2020.05.22
2장 JSX  (0) 2020.05.16
1장 리액트 시작  (0) 2020.05.16
목차  (0) 2020.05.16

2.1 코드 이해하기

create-react-app은 번들러(웹팩, Parcel browserify) 중 웹팩을 사용하는 프로젝트를 생성함.

이로 인해,

- import 구문을 사용해서 모듈 통합이 가능함.

- 최적화 과정에서 파일 분리가 가능함.

- 로더를 통해서 svg, css, 웹폰트, 미디어 파일 등을 불러와서 사용할 수 있음.

- 최신 자바스크립트 파일을 ES5문법으로 변환해줌.

 

2.2 JSX란?

자바스크립트의 확장 문법이며 XML과 유사. 번들링 과정에서 일반 자바스크립트 형태의 코드로 변환됨.

1.번들링 전
function App() {
	return (
    	<div>
        	Hello <b>react</b>
        </div>
    );  
}

2.번들링 후
function App() {
	return React.createElement("div", null, "Hello", React.createElement("b", null, "react")));
}

 

2.3 JSX의 장점

- 보기 쉽고 익숙하다. (html과 유사)

- 활용도가 높다. (html 태그뿐만 아니라, 새로 만드는 컴포넌트도 JSX안에서 작성 가능)

 

2.4 JSX 문법

2.4.1 감싸인 요소

- 부모 요소 하나로 감싸야함. (Virtual DOM에서 컴포넌트 변화를 감지해 낼 때 효율적으로 비교할 수 있도록 하는 컴포넌트 내부는 하나의 DOM트리 구조로 이 류어 져야 한다는 규칙 존재)

1.잘못된 예
import React from 'react';

function App() {
	return (
    	<h1>리액트 안녕!</h1>
        <h2>잘 작동하니?</h2>
	)
}

export default App;

2.올바른 예
import React from 'react';

function App() {
	return (
		<div>
			<h1>리액트 안녕!</h1>
			<h2>잘 작동하니?</h2>    
		</div>
	)
}

export default App;

3.v16이상 Fragment 사용 가능
import React, {Fragment} from 'react';

function App() {
	return (
		<Fragment>
			<h1>리액트 안녕!</h1>
			<h2>잘 작동하니?</h2>    
		</Fragment>
	)
}

export default App;

4.Fragment를 아래와 같은 형태로도 사용 가능
import React, {Fragment} from 'react';

function App() {
	return (
		<>
			<h1>리액트 안녕!</h1>
			<h2>잘 작동하니?</h2>    
		</>
	)
}

export default App;

 

2.4.2 자바스크립트 표현

JSX 내부에서 자바스크립트 표현식을 사용하려면 {}를 사용

import React from 'react';

function App() {
	const name = '리액트';
	return (
		<>
			<h1>{name} 안녕!</h1>
			<h2>잘 작동하니?</h2>    
		</>
	)
}

export default App;

 

2.4.3 If문 대신 조건부 연산자

JSX 내부의 자바스크립트 표현식에서 if문 사용 불가. 때문에 JSX밖에서 if문을 사용하여 사전에 값을 설정하거나, { }안에 조건부 연산자(삼항 연산자)를 사용

import React, {Fragment} from 'react';

function App() {
    const name = '리액트';
    return (
        <div>
            {name === '리액트' ? (
                <h1>리액트 안녕!</h1>
            ) : (
                <h2>잘 작동하니?</h2>
            )}
        </div>
    )
}

export default App;

2.4.4 AND 연산자(&&)를 사용한 조건부 렌더링

특정 조건을 만족할 때만 내용을 보여줄 때 사용.

1.null을 렌더링
import React from 'react';

function App() {
    const name = '뤼액트';
    return (
        <div>{name === '리액트' ? <h1>리액트 입니다.</h1> : null}</div>
    )
}

export default App;

2.false를 렌더링 하는 경우 null과 마찬가지로 취급(0은 예외적으로 화면에 나타남)
import React from 'react';

function App() {
    const name = '뤼액트';
    return (
        <div>{name === '리액트' && <h1>리액트 입니다.</h1>}</div>
    )
}

export default App;

2.4.5 undefined를 렌더링하지 않기

1.함수에서 undefine만 반환하여 랜더링할 수 없음
import React from 'react';

function App() {
    const name = undefiend;
    return name;
}

export default App;

2.OR연산자를 통한 해결
import React from 'react';

function App() {
    const name = undefiend;
    return name || '값이 undefined 입니다.';
}

export default App;

3.JSX내부에서 undefined 랜더링 가능
import React from 'react';

function App() {
    const name = undefiend;
    return <div>{name}</div>;
}

export default App;

2.4.6 인라인 스타일링

- DOM요소에 스타일을 적용할 때 객체 형태로 넣어 주어야 함. (문자열 x)

- 카멜표기법으로 작성해야 함 (background-color ==> backgroundColor)

1.객체를 선언하여 전달
import React from 'react';

function App() {
    const name = '리액트';
    const style = {
        backgroundColor: 'black',  //background-color => backgroundColor
        color: 'aqua', 
        fontSize: '48px', //font-size => fontSize
        fontWeight: 'bold', //font-weight =>fontWeight
        padding: 16
    }
    return (
        <div style={style}>{name}</div>
    )
}

export default App;

2.inline 형태로 전달 시
import React from 'react';

function App() {
    const name = '리액트';
    return (
        <div style={{
            backgroundColor: 'black',
            color: 'aqua',
            fontSize: '48px',
            fontWeight: 'bold',
            padding: 16
        }}>{name}</div>
    )
}

export default App;

2.4.7 class대신 className

JSX에서는 class가 아닌 className으로 class 지정.

(v16이상부터는 class로 지정하면 className으로 변환시켜 주고 콘솔에 경고 띄움._

import React from 'react';

function App() {
    const name = '리액트';
    return (
        <div className="react">{name}</div>
    )
}

export default App;

2.4.8 꼭 닫아야 하는 태그

태그는 꼭 닫아야 함

ex> <input> (x), <input></input>, <input/> (o)

2.4.9 주석

JSX 내부에서 주석을 작성할 때는 {/* !@#!@#!#  */}와 같은 형식으로 작성

import React, {Fragment} from 'react';

function App() {
    const name = '리액트';
    return (
        <>
            {/*주석은 이렇게 작성합니다*/}
            <div 
                className="react" //시작 태그를 여러 줄로 작성하게 된다면 여기에 가능.
            >
                {name}
            </div>
            // 하지만 이런 주석이나
            /*이런 주석은 페이지에 그대로 나타나게 됨*/
        </>
    )
}

export default App;

2.5 ESLint와 Prettier 적용하기

- ESLint : 문법 검사도구, 잘못된 문법 시 경고 메시지 화면에 보임. (VS Code : 보기 > 문제 (상단 메뉴))

- Prettier : 코드 스타일 자동 정리 도구 (VS Code : f1 -> format document), 루트 디렉터리에 .prettierrc를 작성해서 커스터마이징

- 저장할 때 코드 자동 정리 :  Code(파일) > 기본 설정 > 설정 (상단메뉴) 에서 텍스트 박스에 format on save 검색하여 체크. 

 

2.6 정리

JSX는 HTML과 비슷하지만 완전히 똑같지 않음. 코드로 보면 XML 형식이지만 실제로는 자바스크립트 객체이며, 용도와 문법이 조금씩 차이가 남.

'개발 도서 > 리액트를 다루는 기술(개정판)' 카테고리의 다른 글

5장 ref:DOM에 이름 달기  (0) 2020.05.23
4장 이벤트 핸들링  (0) 2020.05.22
3장 컴포넌트  (0) 2020.05.17
1장 리액트 시작  (0) 2020.05.16
목차  (0) 2020.05.16

1.1 왜 리액트인가?

1.1.1 리액트 이해

- 리액트는 오직 V(View)만 신경 쓰는 라이브러리이다.

- 리액트는 초기랜더링을 위해서 render 함수를 제공함. 

-  조화과정 - 리액트가 화면을 변경하는 방식. (변경 전후의 DOM Tree를 비교.)

 

1.2 리액트의 특징

1.2.1 Virtudal DOM

1.2.2 기타 특징

- 리액트는 뷰만 담당함. 다른 기능은 react-router, axios, redux, MobX등의 라이브러리를 사용하여 구현함.

 

1.3 작업 환경 설정

1.3.1 Node.js와 npm

- 설치 : macOS, Ubuntu

$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash 

(Node.js 버전 관리를 위해 nvm을 설치)

$ nvm --version

(버전이 나타나지 않으면 추가 설정 필요)

$ nvm install --lts

(Node.js LTS 버전 설치)

 

- 설치 : Windows

https://nodejs.org/ko/download/ 에서 Window Installer를 내려받아 설치

 

1.3.2 yarn

- macOS (Homebrew를 사용하여 yarn을 설치)

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)(Homebrew 설치 참조 :  https://brew.sh/index_ko)

$ brew update

$ brew install yarn 

$ yarn config set prefix ~/.yarn

$ echo 'export PATH="$(yarn global bin):$PATH"' >> ~/.bash_profile

 

1.3.3 에디터 설치

- VS code 설치.

- VS code 확장 프로그램 설치. ESLint, Reactjs Code Snippets(by charalampos karypidis), Prettier-Code formatter

1.3.4 Git 설치

- macOS https://git-scm.com/download/mac

1.3.5 create-react-app으로 프로젝트 생성하기

$ yarn create react-app hello-react

($ npm init react-app <프로젝트 이름>)

$ cd hellow-react

$ yarn start

'개발 도서 > 리액트를 다루는 기술(개정판)' 카테고리의 다른 글

5장 ref:DOM에 이름 달기  (0) 2020.05.23
4장 이벤트 핸들링  (0) 2020.05.22
3장 컴포넌트  (0) 2020.05.17
2장 JSX  (0) 2020.05.16
목차  (0) 2020.05.16

1장 리액트 시작

2장 JSX

3장 컴포넌트

4장 이벤트 핸들링

5장 ref: DOM에 이름 달기

6장 컴포넌트 반복

7장 컴포넌트의 라이프사이클 메서드

8장 Hooks

9장 컴포넌트 스타일링

10장 일정 관리 웹 애플리케이션 만들기

 

11장 컴포넌트 성능 최적화

12장 immer를 사용하여 더 쉽게 불변성 유지하기

13장 리액트 라우터로 SPA 개발하기

14장 외부 API를 연동하여 뉴스 뷰어 만들기

 

15장 Context API

16장 리덕스 라이브러리 이해하기

17장 리덕스를 사용하여 리액트 애플리케이션 상태 관리하기

18장 리덕스 미들웨어를 통한 비동기 작업 관리

19장 코드 스플리팅

 

20장 서버 사이드 렌더링

21장 백엔드 프로그래밍:Node.js의 Koa 프레임워크

22장 mongoose를 이용한 MongoDB 연동 실습

 

23장 JWT를 통한 회원 인증 시스템 구현하기

24장 프런트엔드 프로젝트: 시작 및 회원 인증 구현

25장 프런트엔드 프로젝트: 글쓰기 기능 구현하기

26장 프런트엔드 프로젝트: 포스트 조회 기능 구현하기

27장 프런트엔드 프로젝트: 수정/삭제 기능 구현 및 마무리

28장 그다음은?

'개발 도서 > 리액트를 다루는 기술(개정판)' 카테고리의 다른 글

5장 ref:DOM에 이름 달기  (0) 2020.05.23
4장 이벤트 핸들링  (0) 2020.05.22
3장 컴포넌트  (0) 2020.05.17
2장 JSX  (0) 2020.05.16
1장 리액트 시작  (0) 2020.05.16

+ Recent posts