---
# System prepended metadata

title: Dream Coding - React 4. Habit Tracker

---

# Dream Coding - React 4. Habit Tracker
## ==4.1 리액트 전반적인 개념 정리 (class vs function component)==

### Class Component

- state 와 lifecycle method를 가지고 있다.
- `render` 함수의 return을 통해서 JSX를 반환
- 다음과 같은 단점이 있어서 Hook을 이용한 Function Component에 밀렸다
    1. class is difficult : 객체 지향 언어를 사용해본적 없는 웹 개발자들에게 어려움
    2. `this` binding issue : `this` 를 이용해서 항상 선언해야하는 불편함과 binding issue
    3. we want functional programming! : 함수형 프로그래밍이 대세로 떠오름
    4. code duplication : 너무 세세하게 lifeCycle이 쪼개져있어서 code가 중복됨

### Function Component

- state와 lifecycle method가 없다. (그래서 Stateless Component 라고 부르기도 함)
- 그러나 **React Hook** 이 등장하면서 state와 lifecycle method를 사용할 수 있게 됨
- `return` 를 통해 JSX를 반환

### 그래서 뭘 배워야 하는데?

- Facebook 에서는 앞으로 새로 작성하는 컴포넌트들은 Function + Hook 로 작성할 것을 권유
- 그러나 기존의 클래스 컴포넌트들을 굳이 함수형 컴포넌트로 리팩토링 X

⇒  따라서 둘다 배워야 함

## ==4.2 템플릿 프로젝트 만들기==

- `public` 폴더 : 정적 파일들 (static)
- `src` 폴더 : 동적 파일들 (dynamic)
- `nocript` 태그 (HTML) : 사용자가 자바스크립트를 돌리지 않을 경우 표시해주는 메세지

    ⇒ 그래서 React를 사용하는 경우 큰 고려 X


## ==4.5 JSX 정리 (HTML 차이점 정리)==

### JSX

 Javascript를 HTML처럼 쓸 수 있게 만들어진 것

- class ⇒ className
- javascript 비지니스 로직 {  }
- 한 Component안에서 return (render) 되는 JSX Node 는 **오직 1개**여야 함
⇒ 불필요한 `<div>` 태그로 묶는것보다는 `React.Fragment` or <> </>를 이용하는 것이 좋음.

### 논리연산자 활용

[조건부 렌더링 - React](https://ko.reactjs.org/docs/conditional-rendering.html)

- expr1 && expr2
	expr1을 true로 변환할 수 있는 경우 expr2을 반환하고,
	그렇지 않으면 expr1을 반환합니다.
- expr1 || expr2	
	expr1을 true로 변환할 수 있으면 expr1을 반환하고,
	그렇지 않으면 expr2를 반환합니다.


## ==4.7 State 이해하기==

### synthethic event

1. **CamelCase** 를 이용함 

    ```jsx
    <button onClick={()=>{console.log("Hello Potato!")}}>
      Activate Lasers
    </button>
    ```

2. 외부 함수를 넘겨줄때 **`()` 를 명시하지 않음**

    ```jsx
    <button onClick={activateLasers}>
      Activate Lasers
    </button>
    ```

3. 인자를 넘겨주고 싶다면 **Arrow Function을 이용**해서 넘겨줄것 (단, event 객체는 자동으로 넘어감)

    ```jsx
    <button onClick={(event)=>this.handleclick(event,this.potato)}>
        Click me
    </button>
    ```

### state

- `this.setState` 를 이용해서 변경해야함
    - `this.state.count++` 등의 **직접 state를 변경하는 것은 위험함**!
    - **immutability** 를 지킬 것

## ==4.7.1 보충설명 (Props에 대해서)==

### props

[Dream Coding](https://academy.dream-coding.com/courses/take/react-basic/texts/16722247-4-7-1-props)

- props는 props를 받은 하위컴포넌트에서 **절대 변경하면 안 됨**
- 변경하고 싶다면, props를 준 컴포넌트에서 변경하도록 해야함
    - 하위 컴포넌트에서 굳이 변경하고 싶다면, 상위 컴포넌트에서 props를 변경할 수 있는 콜백함수를 제공해서 실행시켜야 함. ⇒ 이걸 **State 끌어올리기 (State up)** 이라 함
- 이를 **단방향으로 데이터가 흐른다** 라고 표현

## ==4.8 Habits 컴포넌트 (State up, list key)==

### 배열 컴포넌트 (Array Component)

- 자식 Component에는 반드시 구별할 수 있는 `key` 값이 있어야 함.
    - 불필요한 리렌더링 방지
    - `key` 값은 반드시 고유해야함 (배열의 index 값을 넣지 말 것)

## ==4.9 이벤트 처리하기 part2. State 업데이트 함수들 구현하기==

### immutablity

- react에서는 직접적으로 state로 변경해서는 안 된다.
- object 역시 안의 요소를 수정하는 식으로 해서는 안 된다
- re-rendering을 결정짓도록 comparision을 `shallow comparision` 으로 진행하기 때문!

    ⇒ 변수의 reference (주소값) 만 비교함!

- immutability를 지키기 위해서는 **재할당 method**를 사용하거나, **spread operator를 사용해서 재할당**을 해주는 편이 좋다.

    ex) immutability를 지키지 못한 예제

    ```jsx
    // bad
    this.setState(({user})=>{
    	user=newUser;
    };
    // bad
    this.setState({idList}=>{
    	idList.push(newId);
    }
    ```

    ex) immutability를 잘 지킨 예제

    ```jsx
    // Object good => Using Object.assign
    this.setState((prevState)=>{
    	return Object.assign({},prevState,{user:newUser});
    };
    // Object good => using spread properties
    this.setState(({user})=>{
    	return {
    		...this.state,
    		user: newUser,
    	};
    };
    // Array good => using Array.concat
    this.setState(({idList})=>{
    	return {
    	...this.state,
    	idList : this.state.idList.concat(newID),	
    	}
    }
    // Array good => using spread properties
    this.setState(({idList})=>{
    	return {
    	...this.state,
    	idList : [...this.state.idList,newId],	
    	};
    }
    ```


## ==4.12 Add Form 만들기 (Refs 이용)==

### ref 개념

- JSX 요소를 참고할 수 있게 하는 개념 (Vanila 에서 Element 객체를 반환하는 method와 동일)

### ref 선언

- `inputRef = React.createRef();`

### ref 지정

```jsx
<input
	ref={this.props.inputRef}
  type="text"
  name=""
  id="newHabit"
  className="add-input"
/>
```

### ref 활용

- `const newHabit = this.inputRef.current.value`;


## ==4.14 중요 개념==

### components

### `state`, `render()` => re-render

### Virtual Dom

- 변경된 부분만 html에 반영
- html이 많이 변한다면, react를 제대로 사용하지 않다는 것!
- 잘 변경되는지 확인하기 위해서 chrom 의 react debuggin extenstion을 사용하는 것을 추천

## 4.15  PureComponent활용

### PureComponent

- component에서 `shouldComponentUpdate()` 가 자동으로 구현되어 있는 것
- 목적은 props가 실제로 변경되지 않았을때도, VDOM에서 re-render을 진행하는 것을 방지
    - `shallow comparison` 을 이용해서 props의 변경 여부를 check 함

### Immutability

- props를 받는 하위컴포넌트의 re-render가 생각한 대로 동작하지 않을때 (immutability를 못 지킨 경우), 해결할 수 있는 방법 2가지
    1. 바뀌는 부분만 따로 떼서 props로 전달 
    2. `this.setState` 에서 아예 새로운 Object를 할당

        ⇒ deconstructing을 이용하면 편함 ( call by value 형식으로 복사하기 때문)

## ==4.16 lifecycle 함수들 이해하기==

> **1. 컴포넌트의 생명주기**

[https://ko.reactjs.org/docs/react-component.html#the-component-lifecycle](https://ko.reactjs.org/docs/react-component.html#the-component-lifecycle) 

- **생명주기 (LifeCycle) : 컴포넌트의 생성부터 소멸까지의 과정**
- 전체 생명주기는 다음과 같다

[https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/](https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/)

![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/93f3274e-c15a-4063-a480-7cc2270a0430/Untitled.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/93f3274e-c15a-4063-a480-7cc2270a0430/Untitled.png)

- 자주 사용되는 생명주기는 다음과 같다

### **render( )**

- `render()` 메서드는 클래스 컴포넌트에서 **반드시 구현**되어야 하는 유일한 메서드
- **데이터가 변경**되어 **새 화면**을 그려야 할 때 자동으로 호출되는 함수
- 당연히 함수이기에, **반환값은 오직 1개**여야함

    ⇒ 만약 여러개를 반환하고 싶다면, 의미 없는 최상위 노드를 추가해서 묶거나, Fragment를 이용

    ⇒ 자세한 사항은 [이곳](https://www.notion.so/329538f9a30c4b9ba173b3655e3b8ad9) 참고

- 반환되는 것
    - **JSX** 를 반환 (**React Element**)
    - 배열을 반환 (**Fragment**)
    - **Portal**

### **constructor(props)**

- **맨 처음에 생성될 때 한번만 호출**
- **state를 선언**하거나 **이벤트 처리 method를 바인딩**할때 사용
    - 만약 이 작업이 없다면 호출하지 않아도 됨
- `setState()` 를 **호출하면 안 됨 ⇒ 생성자는 유일하게 `this.state`를 직접 할당할 수 있는 곳**

```jsx
constructor(props) {
  super(props);
  // 여기서 this.setState()를 호출하면 안 됩니다!
  this.state = { counter: 0 };
  this.handleClick = this.handleClick.bind(this);
}
```

### **componentDidMount()**

- **컴포넌트가 마운트** 된 직후 호출
- 즉 **render() 함수가 호출** 된 이후 호출

### **componentDidUpdate(prevProps, prevState, snapshot)**

- **갱신이 일어난 직후 호출** ⇒ 최초 렌더링에서는 호출되지 않음
- **컴포넌트 갱신이후 DOM을 조작**하기 위해서 이 메서드를 활용
- **이전과 현재의 props를 비교하여 네트워크 요청**을 보내는 작업도 이 메서드를 활용

### **componentWillUnmount()**

- **컴포넌트가 소멸되기 직전**에 호출되는 함수
- **컴포넌트에서 감시하고 있는 작업들을 해제**할 때 필요한 함수

    ex) setInterval 함수가 사용 됨 → clearInterval 로 여기서 해제

- 해제 작업이 생략되면, 메모리 누수 현상 (Memory Leak)이 발생할 수 있음

---

위의 5가지 생명주기 함수들은 결국 다음과 같이 작동한다.

```
constructor() -> render() -> componentDidMount() (생성)
render()-> componentDidUpdate() (갱신=> 이 과정은 반복될 수 있음)
componentWillUnmount() (소멸)
```

## ==4.17 function 컴포넌트, memo 정리==

### VSC Component shorcut

 `rcc` : for class
 `rsi` : for fuction

### 함수형 컴포넌트의 활용 및 특징

- this를 쓰지 않아도 됨
- pure Componet ⇒ `React.memo` 이용

    `const Add = memo(~~~)`;

- `render` 함수 ⇒ `return`으로 대체

## 4.18 React Hook

### `useState`

- `this.state` 와 `this.setState` 와 유사한 Hook library
- 사용하기 위해선

    ```jsx
    import React, { useState } from 'react';
    ```

- 사용방법

    ```jsx
    const [value, setValue] = useState(0);
    ```

    1. `useState(param)` 의 parameter : **value의 초깃값 설정**
    2. `useState(param)` 의 반환 값 : 배열
        - 첫 번째 요소 ⇒ **관리할 value**
        - 두 번째 요소 ⇒ **value를 관리할 수 있는 함수** ( `this.setState()` ) 와 유사 )
            - 단, setState와 달리 **대체함(replace)**
        - 보통은 위의 예시 코드와 같이 비구조화 할당을 통해 변수에 할당함
- 주의점
    - `setValue` 를 쓴다고 **즉각적으로 바뀌지 않음**
        - 따라서 즉각적으로 무언가를 반영해야 한다면 **callback function**으로 넘겨야함

        ```jsx
        setPhotoUri(() => {
        					navigation.navigate('Result', {
        						photoUri: newUri,
        					});
        					return newUri;
        				});
        ```

    - Array나 Object의 경우 `setValue` 에서 반드시 **immutable** 하게 넘겨줘야함 (수정 메서드 사용)

        ⇒ Destructor operator 를 사용 ( `[...]` )

### `useEffect`

- [LifeCycle](https://www.notion.so/Component-state-Life-Cycle-in-class-component-c97ebc03131d42fd92b97b267d594517) 에서 `componentDidMount`, `componentDidUpdate` 를 대체
    - Component가 **re-render 될때마다 호출**
    - 즉 React 컴포넌트가 **화면에 렌더링된 이후에 비동기로 처리되어야 하는 부수적인 효과**들을 흔히 **Side Effect**라 부르는데, 이 Side Effect를 처리하기 위한 함수
- 사용하기 위해선

    ```jsx
    import React, { useEffect } from 'react';
    ```

- 사용 방법

    ```jsx
    useEffect(() => {
        console.log('렌더링이 완료되었습니다!');
      },[]);
    ```

    1. useEffect() 의 첫번째 parameter : rendering이 될때 **실행시킬 함수**
        - 이 함수의 **반환 값으로 뒷정리 (clean-up) 코드**를 넣어줄 수 있음
        - `componentWillUnmount` 와 비슷한 효과, 단 **useEffect 가 실행될때 마다** (즉 랜더링이 될 때마다) 뒷정리 코드는 실행됨

        ```jsx
        useEffect(() => {
            console.log('effect');
            console.log(name);
            return () => {
              console.log('cleanup');
              console.log(name);
            };
          });
        ```

    2. useEffect() 의 두번째 parameter : **배열**
        - 배열 안의 **요소가 바뀔 때만** 실행 , 배열 안의 요소는 `useState()` 로 지정한 변수나 `props`
            - **빈 배열** ⇒ `componentDidMount` 일 때만 실행

            ```jsx
            useEffect(() => {
                console.log('마운트 될 때만 실행됩니다.');
              }, []);
            ```

            - **무언가 있는 배열** ⇒ 그 변수가 바뀔때만 실행

            ```jsx
            useEffect(() => {
                console.log(name);
              }, [name]); // name이 바뀔때만 실행됨
            ```

### `useRef`

- Reference를 저장하기 위한 Hook

    `const spanref = useRef();`

### `useCallback`

- 함수를 저장하기 위한 Hook

    `const handleIncre = useCallback(()=>{});`

### 함수형 컴포넌트의 주의점

- 함수형은 전부 반복해서 호출된다. (class는 render만 다시 호출)
- 따라서 props로 전달하고 싶은 변수는 전부 Hook을 사용하여 기억을 해야한다.
- Object로 변수들을 묶을때 정말로 연관되어 있는지 깊게 생각해봐야 함.
    - 싹다 단일 데이터로 관리하면 코드가 지저분해지고
    - Object로 묶다보면 Hook이 제대로 동작하지 않는다.