(1~4번 영상)
리액트 소개 및 특징



(5번 영상)
  • webpack
  1. 코드들을 의존하는 순서대로 하나 또는 여러개의 파일로 만들어줌
  2. gulp 와 비슷. 더 좋다
  1. 여러개의 자바스크립트 파일을 하나도 만들어 주거나 규칙에 따라 분리할 수도 있다.
  2. ES6 - 모던 자바스크립트 사용할 때 구형브라우저에서 지원이 안되서 바벨을 이용해 변환하여 여러종류의 브라우저에서 실행 하능
  3. 프로젝트를 만들 때 전체적으로 파일들을 관리해 주는 도구

  • babel
  1. 자바스크립트 변환 도구
  2. 노드나 자브스크립트 엔진에서 모든 문법을 지원해 주지는 않음
  3. 리액트는 JSX 문법을 사용해 컴포넌트를 작성하는데 이때 바벨을 사용함

codesandbox 사용 (https://codesandbox.io/)
리액트 샘플) http://bit.ly/beginreact


[문법]
import : 모듈을 사용함
class : Component 를 만듬 (다른 방법 - 함수를 통해서 만들 수 잇음)
render : 반드시 JSX 형태의 코드를 return 해줘야 함




(6번 영상)
  • JSX : HTML 처럼 생긴 문법이 자바스크립트 코드로 변환됨
  1. 태그는 반드시 받혀야 한다
  2. 최상위 element는 꼭 하나여야 한다. (태그가 2개 이상일 경우 최상위에 하나의 태그로 감싸줘야함)
    이 경우 불필요한 최상위 element가 하나 생기게 되는데 React 16.2 이상에서 fragment 기능으로 방지할 수있다.
  3. JSX 안에서 자바스크립트 값을 사용할 때는 {변수명} 으로 사용한다
  4. var 변수는 scope 가 함수 단위이다.
function foo(){                scope 단위    ┐
    var a = 'hello'                          │
    if(true) {                               │
        var a = 'bye'                        │
        console.log(a) // bye                │
    }                                        │
    console.log(a) // bye                    ┘
  1. const, let 변수는 scope 가 블록 단위이다.
function foo(){                scope 단위         ┐
    let a = 'hello'                               ┘
    if(true) {                               ┐
        let a = 'bye'                        │
        console.log(a) // bye                ┘
    }                                             ┐
    console.log(a) // bye                         ┘
  1. ES6 에서 var 은 더이상 쓰지 않음
    고정 상수는 const, 일반 변수는 let 사용
  2. JSX 내부에서 조건식 사용하기
    1)  삼항 연산자 사용 ( 조건 ? true : false )
    2)  && 연산자 사용
    3)  function 함수 작성 ( => 화살표 함수로도 사용 가능. 화살표 함수는 this, argument super 가 없는 함수임)


+ self closing tag : <input />



(7번 영상)
@ JSX 에서 css 스타일과 class 사용방법

React 사용방법은 기존 css 사용법과 조금 다르다
  1. Style 을 객체 형태로 넣어줌
  2. 속성은 기존 단어가 아닌 특수문자를 제외하고 camel case 로 적는다.
  3. class 는 className 으로 입력해야 한다.
const style = {
    backgroudColor : 'red',   // 기존 : backgroud-color
    color : 'white',
    fontSize : '36px'         // 기존 : font-size
}

// 적용방법
<div style={style} className="app">
</div>

  1. JSX 내부에서 주석은 그냥 출력되어 버린다.
    일반 주석 및 멀티라인 주석 모두 출력됨.
    일반적으로 주석은 멀티라인으로 작성하고 {} 로 감싸준다
return {
    <div>
        // 주석
        /*
            주석
        */
        위 두 주석 모두 오류
        일반적으로 주석은 멀티라인
        {/* 주석 사용 */}
        태그 사이에는 그냥 주석 사요 가능
        <h1
            // 주석 가능
        >
        </h1>
    </div>
}





(8번 영상)
주제 : Props

  • Props : 부모에서 자식으로 일방적으로 전달. 자식에서 값을 변경할 수 없다.(읽기 전용)
  1. <Child value = "value">    : value 가 props 이다
  2. default props 값을 class 내부에 static 으로 지정해 놓을 수 있다
    class 외부에 설정할 수 있지만 static 으로 사용하는게 최신 자바스크립트 문법에 더 알맞다.
- 기본 static 사용법 (최신 사용법)
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {

static defaultProps = {
name : 'basic'
}
render() {
return (
<div className="App">
props test : {this.props.name}
</div>
);
}
}
export default App;

- 외부 설정
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {

render() {
return (
<div className="App">
props test : {this.props.name}
</div>
);
}
}

App.defaultProps = {
name : 'basic'
}

export default App;


  • 단순히 불러오기만 할 class 일 경우 함수형 component 로 만든다
- SampleFunctionalCoimponent.js
import React from 'react'

const SampleFunctionalComponent = ({ test }) => {
return (
<div>hi this is sample functional component : {test}</div>
);
};

SampleFunctionalComponent.defaultProps = {
test : 'test hi'
}

export default SampleFunctionalComponent;

- App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

import SampleFunctionalComponent from './SampleFunctionalComponent'

class App extends Component {

static defaultProps = {
name : 'basic'
}
render() {
return (
<SampleFunctionalComponent />
);
}
}
export default App;

1) import 에 Componenet 선언이 필요없다
2) class 선언이 아니고 하나의 변수로 만든다
3) 함수형 컴포넌트의 파라미터 (=test) 는 비구조화 할당 문법이 사용됨.
4) 

* 비구조화 할당 문법
 : 여러 변수 또는 파라미터를 각각의 값에 맞게 할당할 때 하나씩 지정해 주지 않고 객체로 한번에 지정해 주는 방식

  • 함수형 컴포넌트와 클래스형 컴포넌트의 차이점 (함수형 컴포넌트 기준)
  1. state 기능이 없음
  2. life cycle 없음
    > 장점
  1. 초기 마운트 속도가 미세하게 빠르다
  2. 불필요한 기능이 없어서 메모리 자원을 덜 사용한다
- 어떤값을 가져와서 단순히 보여주기만 한다면 함수형 컴포넌트가 약간 더 효율적이다
- 컴포넌트가 매우매우 많다면 조금 더 효율적이겠지만 크게 차이나지는 않을 것이다.



Class Field 문법 : https://tc39.github.io/proposal-class-fields/

(9번 영상)
주제 : state


* state : 컴포넌트 스스로가 가지고 있는 객체. 따라서 컴포넌트 스스로가 값을 변경 할 수 있다. (setState 사용)


- 카운터 하는 소스 작성... ( 카운터에 나오는 숫자는 유동적. 숫자가 바뀔때 마다 rerender 해줘야 한다. )

* 아래는 전부 class 안에 정의한다.

1) state 정의 : 객체여야 한다. 문자열, 숫자 안됨.

2) 객체 안에 요소를 정의 한다.

3) 카운터 값을 변경하기 위해 custom method 를 만든다.

4) 카운터 기능을 위해 증가 감소 함수를 만드는데, 함수 안에서 state 값을 직접 조절하면 안된다.

    컴포넌트에서 state 값이 update 된지 모른다.

5) state 값이 변경되는걸 component 가 알기 위해서는 항상 setState 함수를 통해 변경해줘야 한다.


- 잘못된 state 사용방법

handleIncrease = () => {
this.state.counter = this.state.counter + 1;
}


- 올바른 사용방법

import React, { Component } from 'react';

class Counters extends Component {
state = {
counter : 0
}
handleIncrease = () => {
this.setState({
counter : this.state.counter + 1
})
}
handleDecrease = () => {
this.setState({
counter : this.state.counter - 1
})
}
render(){
return(
<div>
<h1>counter</h1>
<div>value : {this.state.counter}</div>
<button onClick={this.handleIncrease}>+</button>
<button onClick={this.handleDecrease}>-</button>
</div>
);
}
}

export default Counters;


* render 함수는 그냥 함수로 작성했는데 increase, decrease 함수는 왜 화살표 함수( => )로 작성했을까?

  : 증감 함수를 화살표가 아닌 기본 함수로 작성하게 되면 함수 안에서 this 가 어느것을 가리키는지 모르게 된다.

  : 해당 문제를 해결해주기 위해서는 constructor 를 이용해야 한다.

    1) counter component 가 생성될 때 항상 constructor 가 제일 먼저 실행되고,

    2) constructor 에서는 상속받은 Component 의 기본 생성함수를 먼저 호출해주도록 한다. ( super 사용 )

    3) 그 다음 counter component 에서 사용되는 increase, decrease 함수의 this 가 constructor 의 this 라는걸 명시해 준다. ( binding 해줌 )


- 예시

import React, { Component } from 'react';

class Counters extends Component {
state = {
counter : 0
}

constructor(props){
super(props);
this.handleIncrease = this.handleIncrease.bind(this);
this.handleDecrease = this.handleDecrease.bind(this);
}

handleIncrease() {
this.setState({
counter : this.state.counter + 1
})
}
handleDecrease = () => {
this.setState({
counter : this.state.counter - 1
})
}
render(){
return(
<div>
<h1>counter</h1>
<div>value : {this.state.counter}</div>
<button onClick={this.handleIncrease}>+</button>
<button onClick={this.handleDecrease}>-</button>
</div>
);
}
}

export default Counters;



* props 는 부모자 자식에게 넘겨주는 변경 불가능한 값

* state 는 자기 자신이 가지고 있는 변경 가능한 값




lifecycle api : https://react-anyone.vlpt.us/05.html




(10번 영상)
주제 : life cycle api

* life cycle api 사용 시기

 1) component 가 브라우저에 나타날 때

 2) component 가 브라우저에서 업데이트 될 때

 3) component 가 브라우저에서 사라질 때



* 종류 (매우 많다)


1. Mount - Component 가 브러우저에 나타남

  1) constructor : Component 가 만들어질 때 가장 먼저 실행되는 함수

  2) getDerivedStateFromProps : props 로 받은 값을 그대로 state 에 동기화 시키고 싶을 때 사용 (mount, update 두 부분에서 사용)

  3) render : DOM, 태그 등등 정의

 * 이후 브라우저에 표시되고 난 다음

  4) componentDidMount : 외부 라이브러리, 차트 라이브러리 등등 사용할 때, ajax, api 요청을 할 때 이곳에서 실행

                                    뷰가 다 그려지고 스크롤을 이동, 이벤트 listening


2. Update - Component 에서 props, state 값이 변경됨

  1) getDerivedStateFromProps : props 로 받은 값을 그대로 state 에 동기화 시키고 싶을 때 사용 (mount, update 두 부분에서 사용)

  2) shouldComponentUpdate : (중요) component 가 update 되는 성능을 최적화 시킬 때 사용

   - 부모 component 가 rerender 되면 자동적으로 자식 component 도 rerender 된다. 하지만 불필요할 때가 있다.

   - react 는 virtual DOM 을 사용하지만 기본적으로는 rerender가 발생하면 기본 DOM 과 virtual DOM 둘 다 다시 그린 후 변경점을 비교하게 된다

   - 이 기능을 사용하게 되면 virtual DOM 에 그리는 것조차 막아서 뷰의 변경을 방지 할 수 있다. (성능 최적화 관점)

   - 해당 함수는 true, false 값을 반환하며, true 는 render 실행, false 는 실행 안함

 * render 가 실행되고 브라우저에 반영되기 바로 직전

  3) getSnapshotBeforeUpdate : render 되고 브라우저에 표시되기 전에 이 함수에서 특정 로직을 수행한다.

   - 스크롤 위치, DOM 크기 가져오기 등등

 * 위 작업들을 모두 마치고 component 가 모두 update 되고난 후

  4) componentDidUpdate : state 가 변경되었을 때 이전 상태와 현재 상태를 비교해서 특정 작업을 해야할 때


3. Unmount - Component 가 브러우저에서 사라짐

  1) componentWillUnmount : 마운트 때 listen 시킨 이벤트들을 해제할 때 사용됨





lifecycle api : https://react-anyone.vlpt.us/05.html

(11번 영상)
주제 : life cycle api

* 코드 샘플

1. constructor
 - 컴포넌트가 제일 먼저 만들어질 때 호출됨.
 - super 사용 용도 : 상속받은 Component 의 원래 가지고 있던 생성자를 먼저 호출해 주고 작업을 하도록 하기 위함

class App extends Component {
constructor(props){
super(props);
console.log('constructor')
}
........
}

2. componentWillMount
 - 사라짐

3. componentDidMount

class App extends Component {

constructor(props){
super(props);
console.log('constructor')
}
componentDidMount(){
console.log('componentDidMount')
}

.................

}


* 특정 DOM 에 어떤 작업을 하고 싶을 때 ref 사용. ( 태그에 아이디를 붙이는 것과 비슷함. ref 로 직접 가져올 수 있다. )
class App extends Component {
constructor(props){
super(props);
console.log('constructor')
}
componentDidMount(){
console.log('componentDidMount')
console.log(this.myDiv.getBoundingClientRect())
}
render() {
return (
<div ref={ref => this.myDiv = ref}>
hi
</div>
);
}
}



4. componentWillReceiveProps

 - 16.3 부터 사라짐


5. getDerivedStateFromProps

 - 16.3 부터 사용 가능

 - setstate 사용 불가.

 - 변경 할 state 값을 바로 return 해주면 setState 사용하지 않고도 state 에 값이 적용된다.

 - state 와 props 값의 동기화


[StateComponent.js]

import React, { Component } from 'react';
class StateComponent extends Component {
state = {
value : 0
}
static getDerivedStateFromProps(nextProps, prevState){
if(prevState.value != nextProps.value){
return {
value : nextProps.value
}
}
return null;
}
render(){
return(
<div>
<p>props : {this.props.value}</p>
<p>value : {this.state.value}</p>
</div>
);
}
}

export default StateComponent;


[App.js]

import React, { Component } from 'react';
import StateComponent from './StateComponent'
class App extends Component {
state = {
count : 1
}
constructor(props){
super(props);
console.log('constructor')
}
componentDidMount(){
console.log('componentDidMount')
// console.log(this.myDiv.getBoundingClientRect())
}

handleClick = () => {
this.setState({
count : this.state.count + 1
})
}

render() {
return (
<div>
<h1>hi</h1>
<StateComponent value={this.state.count} />
<button onClick={this.handleClick}> click </button>
</div>
);
}
}
export default App;



6. shouldComponentUpdate

 - 다음 받아올 props, state 값을 가져옴

 - return 값에 따라 값의 업데이트 여부가 결정됨 ( true : 업데이트 , false : 안함 )

 - 특정 조건에서 update 를 막아줄 수 있는 함수


7. componentWillUpdate

 - 사용하지 않음



8. getSnapshotBeforeUpdate

 - update 되기 바로 직전 DOM 상태를 return

 - 직전 상태 (스크롤 위치 등) 를 componentDidUpdate 를 통해서 유지 시킬 수 있다.



9. componentDidUpdate

 - getSnapshotBeforeUpdate 에서 획득한 이전 상태를 3번째 파라미터로 받아 작업 진행



10. componentWillUnmount

 - component 가 사라질 때 호출됨


* sample : count 가 10이 넘어가면 StateComponent 를 더이상 표시하지 않게되고

              StateComponent 가 사라지면 StateComponent 클래스에 구현된 componentWillUnmount 에 의해 특정 로직이 수행됨


[App.js]

render() {
return (
<div>
<h1>hi</h1>
{ this.state.count < 10 && <StateComponent value={this.state.count} /> }
<button onClick={this.handleClick}> click </button>
</div>
);
}



11. componentDidCatch

 - component 에서 에러가 발생했을 때 확인할 수 있음

 - render 함수 안에서 에러가 나면 app 자체가 crash 발생함

 - 에러를 캐치하기 위해서는 자식 component 에서는 불가능하고 부모 component 에서만 가능하다





(12번 영상)
주제 : 필요 도구 설치

* 개발환경 설정

1. Node.js 설치 (webpack, babel 을 사용하기 위해 필요)
 - NVM (Node Version Manager) 사용하면 편하다 (추천)  : https://github.com/creationix/nvm


2. yarn 사용 : https://yarnpkg.com/en/docs/install#windows-stable
 - Node.js 를 설치하면 기본적으로 NPM 이 설치되지만, 대신 yarn 을 사용하는걸 추천.
 - NPM 보다 좀더 개선된 버전이라고 보면 됨.


3. IDE
 - 익숙한것 사용하기
 - vscode : https://code.visualstudio.com/


4. git : https://gitforwindows.org/
 - 형상관리


자세한 설치방법은 추후 업데이트



(13번 영상)
주제 : create react app 사용

1. 설치 확인

 - Node.js 버전 확인 :  $ node -v

 - yarn 버전 확인 :  $ yarn -v


2. create-react-app 설치 : https://github.com/facebook/create-react-app

 - 페이스북에서 만든 react 프로젝트를 통합 설치해주는 툴

 - webpack, babel 설치 및 설정을 간소화 시켜줌


설치

$ npm install -g create-react-app

$ create-react-app hello-react

or

$ npx create-react-app my-app



* 프로젝트가 생성되면 개발을 시작해보자!




14번






15번

[배열에 데이터 삽입하기]

(참고)


* 자식 컴포넌트에서 부모 컴포넌트로 값 전달하기


1. 부모 컴포넌트에서 handleCreate 라는 메소드를 만들고 자식 컴포넌트로 props 로 전달한다.
2. 자식 컴포넌트에서 props 로 전달받은 handleCreate 메소드를 호출해서 데이터가 부모 컴포넌트로 전달되도록 한다.

* 기본 form 속성으로 버튼 type 이 submit 일 경우 클릭하면 페이지가 새로고침 된다.
  해당 새로고침을 방지하기 위해 handleSubmit 함수를 작성해준다.

* 리액트에서는 불변성을 꼭 유지해 줘야한다.
* 어떤 값을 수정할때는 꼭 setState 를 사용해야하며, 그 내부의 배열이나 객체를 수정해야 할 때는
   기존 배열, 객체를 수정하지 않고 원본을 기준으로 새로운 배열, 객체를 만들어서 값을 주입해 주어야 함.
* 배열에 추가하는 방식은 concat 사용 (C 언어에서 문자열 이어붙이기와 같은 명령어)

* 배열에 고유한 id 값이 증가하면서 추가되도록 할 때는
  1. '... spread 전개 연산자'를 사용
  2. 기존 속성 값을 그대로 입력
  3. object.assign 객체 사용

* state 에 변수를 선언하는 이유는, render 함수에서 사용하면서 변수가 수정되었을 때 꼭 rerender 되게끔 만들게 하기 위함

[App.js - 새로고침 방지]

handleSubmit = (e) => {
e.preventDefault();
this.props.onCreate(this.state);
this.setState({
name: '',
phone: '',
})
}


[자식 컴포넌트]
- 부모 컴포넌트로 props 전달


[App.js - 배열에 고유 id 값 증가 방법]
1)
handleCreate = (data) => {
const { information } = this.state;
this.setState({
information: information.concat({
...data,
id: this.id++,
})
});
}

2) 
handleCreate = (data) => {
const { information } = this.state;
this.setState({
information: information.concat({
name: data.name,
phone: data.phone,
id: this.id++,
})
});
}

3) 
handleCreate = (data) => {
const { information } = this.state;
this.setState({
information: information.concat( Object.assign({}, data, {
id: this.id++
}))
});
}




16번


[자바스크립트 배열 내장 함수 - map]

(참고)

* 기본 배열 선언 : numbers = [1,2,3];
* map 사용 : squared = numbers.map(n => n * n);
* 사용 -> squared : [1, 4, 9]  -> 기존 numbers 배열을 제곱으로 만들어줌

- defaultProps 지정해 줄때는 항상 static 으로 선언해야 한다.


* 배열에서 키가 없다면 리스트 항목을 추가 제거할 때 매우 비효율적으로 동작한다.

[PhoneInfoList.js]
render() {
const { data } = this.props;

const list = data.map(
info => (<PhoneInfo info={info} key={info.id} />)
);
return (
<div>
{list}
</div>
);
}




17번

[배열 조작]


(참고)

* 배열은 항상 불변성을 유지해야 한다.
* slice 와 concat 을 혼합해서 배열의 중간 값만 제거할 수 있다.
* 제거 방법
 1) slice : 파라미터 (a,b) - a번째에서 시작해서 b번째 까지만 가져온다
 2) filter : 조건으로 값을 가져올 수 있다. - 기존 배열을 변경하지 않는다.

ex) slice


ex) filter

[App.js]
handleRemove = (id) => {
const { information } = this.state;
this.setState({
information: information.filter(info => info.id !== id)
});
}



1





(18번 영상)
[배열 안의 데이터 수정하기]

*  일반적인 데이터 수정 방법 2가지
[
...numbers.slice(0,2),
9,
...numbers.slice(3,5)
]

numbers.map(n => {
if (n == 3) {
return 9;
}
})







(19번 영상)
[shouldComponentUpdate 를 통한 최적화. 불변성을 왜 유지하는가?]

(참고)
Immutable.js : https://facebook.github.io/immutable-js/
Immer.js : https://github.com/mweststrate/immer

* 중첩된 render 가 호출되면 변하지 않는 항목이 다시 render 되는 불필요한 상황이 발생한다
* shouldComponentUpdate 를 통해 방지 할 수 있다.

* 배열, 객체는 call by reference 이므로 하나의 변수를 다른 변수에 동일하게 지정하도록 하면 하나를 변경하면 둘 모두 변경된다.
ex) a = [0,1,2]
     b = a
     b.push(3)
     b = [0,1,2,3]
     a = [0,1,2,3]

* 이럴때는 지정이 아닌 새로운 변수로 만들어지도록 해야한다.
ex) a = [0,1,2]
     b = [...a, 3]

이러한 객체나 배열이 길어지거나 깊어지면 복잡해지는데, 이럴 때 사용하기 좋은 라이브러리가 있다. (참고 확인)




(20번 영상)

[이름으로 전화번호 찾기]

* keyword state 를 추가하고 render 안에서 PhoneInfoList 컴포넌트의 data 속성에 바로 filter 기능을 넣어 검색 가능하도록 만든다





(21번 영상)

[Ref 를 통하여 DOM 에 직접 접근하기


* Ref 사용법 2가지

 1) 함수 사용 : 태그 속성에 ref 함수를 작성. id 를 지정해주는 것과 비슷한듯


 2) (react 16.3 버전 이상에서만 가능)

     상단에 id 설정해 줄때 React.createRef() 를 사용한다

     focus 를 호출할 때는 1번과 다르게 이름 뒤에 current 를 꼭 붙여줘야한다.


input1 = null
input2 = React.createRef();

handleSubmit = (e) => {
e.preventDefault();
this.props.onCreate(this.state);
this.setState({
name: '',
phone: '',
});
// this.input1.focus()
this.input2.current.focus();
}

render() {
return (
<form onSubmit={this.handleSubmit}>
<input
name="name"
placeholder="이름"
onChange={this.handleChange}
value={this.state.name}
ref={this.input2}
// ref={ref => this.input1 = ref}
/>
<input
name="phone"
placeholder="전화번호"
onChange={this.handleChange}
value={this.state.phone}
/>
<button type="submit">등록</button>
</form>
);
}






(22번 영상)

[마치면서]


추천)


1. prettier : 코드 정리

2. 리액트 컴포넌트 스타일링 : css, sass 스타일 컴포넌트를 쉽게 사용할수 잇음

3. immutable.js : 불변성 변수 사용

4. immer.js : 3번과 비슷한데 엄청 비슷

5. 리덕스 : 데이터 관리 시 update 로직을 다른 파일로 분리, 컴포넌트 등 프로젝트 구조를 체계적으로 만들 수 있음

              상태 관리 라이브러리

6. 몹X 라이브러리 : 리덕스랑 비슷? 찾아봐야함

7. 리액트 라우터 v4 : 여러 페이지로 프로젝트를 구성해야 할 때

8. 타입스크립트 : 컴포넌트를 더 확실하게 사용하고 싶을때

9. Jest, Enzyme : 테스트 코드 개발 시 사용


























'공부 > 프로그래밍' 카테고리의 다른 글

[VScode] c++ 개발환경 설정  (0) 2020.01.25

+ Recent posts