# 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/)

- 자주 사용되는 생명주기는 다음과 같다
### **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이 제대로 동작하지 않는다.