todo list frago88
Redux 모듈에서 state를 깊은 복사 후 다루도록 변경하였다.
Header
컴포넌트에서 background-image가 제대로 불러와 지지 않는 문제를 수정하였다.
리액트 강의 듣기
함수와 연산자에 전달되는 값은 대부분 적절한 자료형으로 자동 변환됩니다. 이런 과정을 "형 변환(type conversion)"이라고 합니다.
문자형으로 변환
무언가를 출력할 때 주로 일어납니다. String(value)을 사용하면 문자형으로 명시적 변환이 가능합니다. 원시 자료형을 문자형으로 변환할 땐, 대부분 그 결과를 예상할 수 있을 정도로 명시적인 방식으로 일어납니다.
숫자형으로 변환
수학 관련 연산시 주로 일어납니다. Number(value)로도 형 변환을 할 수 있습니다.
숫자형으로의 변환은 다음 규칙을 따릅니다.
전달받은 값 | 형 변환 후 |
---|---|
undefined | NaN |
null | 0 |
true / false | 1 / 0 |
string | 전달받은 문자열을 “그대로” 읽되, 처음과 끝의 공백을 무시합니다. 문자열이 비어있다면 0이 되고, 오류 발생 시 NaN이 됩니다. |
불린형으로 변환
논리 연산 시 발생합니다. Boolean(value)으로도 변환할 수 있습니다.
불린형으로의 형 변환은 다음 규칙을 따릅니다.
전달받은 값 | 형 변환 후 |
---|---|
0, null, undefined, NaN, "" | false |
그 외의 값 | true |
형 변환 시 적용되는 규칙 대부분은 이해하고 기억하기 쉬운 편에 속합니다. 다만 아래는 예외적인 경우이기 때문에 실수를 방지하기 위해 따로 기억해 두도록 하자.
Reducer 함수에서 State를 조작할 때는 깊은 복사를 해야한다. 이유는 기존 State 원본과 확실히 달라야 하기 때문이다.
객체는 값이 같아도 비교할땐 False로 나온다
{ a : 1 } === { a : 1 } // false
값은 같아도 서로 다른 주소값을 참조하기 때문이다.
그렇기 때문에 깊은 복사를 통해 원본 배열과 확실히 달려지게 해야
React가 state가 확실히 바뀌었음을 인식하고 리랜더링을 하기 때문이다.
예시 코드
// Redux 의 리듀서 함수
const todos = (state = initialState, action) => {
switch (action.type) {
case INPUT_TODO:
let copyTodosForInp = state // state를 깊은 복사
return {
...copyTodosForInp,
todos: [...copyTodosForInp.todos, action.payload],
};
default:
return state;
}
}
Ducks 패턴은 구조중심이 아니라 기능중심으로 파일을 나눈다. 그래서 단일기능을 작성할때나 기능을 수정할 때 하나의 파일만 다루면 되므로 직관적인 코드작성이 가능하다.
즉, action type, action생성자 함수, saga, reducer를 하나의 파일에서 관리하는것이다.
Ducks패턴에서 각각의 액션/액션함수/리듀서를 모아둔 것을 module이라고 부른다
지켜야할 점
1. reducer는 export default로 내보낸다.
2. action 함수는 export로 내보낸다.
3. 액션타입을 정의할 때 reducer/ACTION_TYPE형태로 적어준다. 이렇게 접두사를 붙여주는 이유는 서로다른 리듀서에서 액션이름이 중첩되는것을 방지하기위해서이다.
이러한 규칙을 지켜서 아래와 같이 하나의 파일에 한가지 기능에 대한 내용을 작성할수 있다.
// widgets.js
// Actions
const LOAD = 'widgets/LOAD';
const CREATE = 'widgets/CREATE';
const UPDATE = 'widgets/UPDATE';
const REMOVE = 'widgets/REMOVE';
// Reducer
export default function reducer(state = {}, action = {}) {
switch (action.type) {
// do reducer stuff
default: return state;
}
}
// Action 생성자
export function loadWidgets() {
return { type: LOAD };
}
export function createWidget(widget) {
return { type: CREATE, widget };
}
export function updateWidget(widget) {
return { type: UPDATE, widget };
}
export function removeWidget(widget) {
return { type: REMOVE, widget };
}