들어가며
저번주 금요일(08/25)부터 3주간에 걸쳐 진행될
[Chapter 3] 주특기 주차가 시작되어
Lv.1 ~ 5 까지 페어 프로그래밍으로 과제가 진행될 예정입니다.
저번주는 Lv.1 개인과제로 React 를 통해 todolist 를 만들어 보는 과제를 수행했습니다.
이번주 Lv.2 페어과제는 비슷한 시간에 제출한 분들 중 한 분과 페어를 이루어
1주차에서 만든 todolist 를 2주차인 숙련주차 강의시간에서 배운
Redux, Router-dom, Styled-Components패키지를 이용해 디벨롭시켜보는 과제였습니다.
과제 요구사항
- todos(할 일들) 데이터는 Redux 를 사용해 전역상태로 관리
- 모듈 구현 시 Ducks 패턴 사용
- Router-dom 을 이용해 todo 상세페이지 생성 및 연결
- 프로젝트의 스타일은 Styled-Components 이용
과제를 수행하며
Lv.2 리덕스를 이용한 todolist 를 진행하면서 스토어(Store)라는 이름의 전역 자바스크립트 변수를 통해 상태변화를 한 곳에서 관리하는 "중앙화" 가 전역 상태를 관리할 때 효율적이라는 점을 알았습니다.
또한 크고 복잡한 앱에서 확장성이 높고, 리덕스는 상태를 읽기 전용으로 취급하기에 이전 상태로 돌아가기 위해서는 그저 이전 상태를 현재 상태에 덮어쓰기만 하면 된다는 점을 리덕스를 사용하며 배웠습니다.
리덕스도 단방향 데이터 흐름을 갖고 있기 때문에 버그를 예측하기에 용이합니다.
https://github.com/Goyka/react-redux-todo
GitHub - Goyka/react-redux-todo: Web App based on React.js & Redux
Web App based on React.js & Redux. Contribute to Goyka/react-redux-todo development by creating an account on GitHub.
github.com
react-redux-todo info
수행한 프로젝트의 기능들을 폴더별로 설명해보겠습니다.
- components
- TodoCreate.jsx : TodoItem 생성
- TodoList : TodoItem 나열
- TodoItem : 할 일
- Modal.jsx : 모달창
- modules
- store.js : 전역 상태 관리
- reducer.js : 전역 상태 변화를 일으키는 함수 reducer
- actions.js : 액션을 만드는 함수. 단순히 파라미터를 받아와서 액션 객체 형태를 생성.
- config.js
- Router.js : Router-dom 으로 페이지 라우팅
- pages
- Home.jsx : 메인페이지
- TodoDetail.jsx : 상세페이지
modules
store.js
리덕스에서는 한 애플리케이션 당 하나의 스토어를 만들게 됩니다. 스토어 안에는 현재의 앱 상태와, 리듀서가 들어가 있고, 추가적으로 몇 가지 내장 함수들이 있습니다. 여기 있는 store.js 에서 그런 역할을 수행하고 있습니다.
import { createStore } from "redux";
import { reducer } from "./reducer";
import { combineReducers } from "redux";
const rootReducer = combineReducers({ reducer });
const store = createStore(rootReducer);
export default store;
combineReducers 를 통해 리듀서파일 하나 뿐만 아니라 여러 리듀서 파일들이 생길 것을 고려해 사용됩니다.
store 라는 변수에 createStore 를 통해 전역상태로 객체를 하나 만듭니다.
action.js
상태에 어떠한 변화가 필요하게 될 때, 액션이라는 것을 발생시키는데, 이는 객체로 표현돼 액션객체라고도 표현합니다. 액션 객체는 type 이라는 키를 필수적으로 가지고 있고, 나머지는 개발자 마음입니다. 이러한 액션객체들을 컴포넌트에서 편하게 선언하기 위해 따로 생성하는 것을 액션 생성함수(Action Creator)라고 하고, 이를 action.js 한 곳에서 관리합니다.
export const ADD = "ADD";
export const DELETE = "DELETE";
export const DONE = "DONE";
export const DETAIL = "DETAIL";
export const add_todo = (todo) => { ①
return {
type: ADD,
todo: {
id: todo.id,
title: todo.title,
value: todo.value,
isDone: todo.isDone,
},
};
};
export const delete_todo = (id) => { ②
return {
type: DELETE,
id,
};
};
export const done_todo = (id) => { ③
return {
type: DONE,
id,
};
};
export const detail_todo = (todo) => { ④
return {
type: DETAIL,
todo: {
id: todo.id,
title: todo.title,
value: todo.value,
},
};
};
① add_todo 함수는 메인페이지에 있는 TodoCreator.js 컴포넌트 파일에서 입력한 todo 데이터를 매개변수로 받아 이를 액션 객체의 속성으로 포함해 리듀서 함수로 전해줍니다.
② delete_todo 함수는 메인페이에 있는 TodoItem.js 컴포넌트 파일에 있는 '삭제' 버튼을 누르면 해당 TodoItem 의 id 속성값을 매개변수로 받아 이를 액션 객체의 속성으로 포함해 리듀서 함수로 전해줍니다.
③ done_todo 함수는 메인페이지에 있는 TodoItem.js 컴포넌트 파일에 있는 '완료' 버튼 또는 '취소' 버튼 을 누르면 해당 TodoItem 의 id 속성값을 매개변수로 받아 이를 액션 객체의 속성으로 포함해 리듀서 함수로 전해줍니다.
④ detail_todo 함수는 메인페이지에 있는 TodoItem.js 컴포넌트 파일에서 상세보기를 클릭하면, 해당 TodoItem 의 id 속성값을 매개변수로 받아 이를 액션 객체의 속성으로 포함해 리듀서 함수로 전해줍니다.
reducer.js
reducer.js 에서는 컴포넌트들의 상태 관련 로직들을 다른 파일들로 분리시켜서 효율적으로 관리하기 위해 이후에 있을 action 객체를 이용해 dispatch 로 reducer 함수들을 모아둔 곳입니다. configStore.js 에서 전역에서 상태를 불러 가져올 수 있는 store 라는 객체(상태)를 관리하기 위한 곳으로 전역으로 선언된 변수에 대한 관리가 여기 한 곳에서 이루어집니다.
리듀서 함수를 실행시키기 위해 필요한 action 객체들은 action.js 파일에 따로 관리합니다.
import { ADD, DELETE, DONE, DETAIL } from "./actions";
const initState = {
todos: [],
detailTodos: {},
};
export const reducer = (state = initState, action) => {
switch (action.type) {
case ADD:
return { ...state, todos: [...state.todos, action.todo] };
case DELETE:
return {
todos: [...state.todos.filter((todo) => todo.id !== action.id)],
};
case DONE:
return {
todos: state.todos.map((todo) =>
todo.id === action.id ? { ...todo, isDone: !todo.isDone } : todo
),
detailTodos: action.todo,
};
case DETAIL:
return {
todos: [...state.todos],
detailTodos: action.todo,
};
default:
return state;
}
};
export default reducer;
① action.js 에서 선언된 액션객체를 반환하는 함수들을 import 합니다.
② initState 는 전역상태가 담기는 store 객체의 초기값으로 todos 는 할 일 아이템들이 객체로 순서대로 쌓여야 하기 때문에 빈 배열로 선언하고, detailTodos 는 상세페이지에 들어갈 때, 해당 할 일 아이템의 정보 하나만을 담아야 하기 때문에 빈 객체로 선언합니다.
③ ADD 타입은 TodoCreator 에서 새롭게 생성된 할 일 아이템의 정보들(id, title, value)이 담긴 객체를 매개변수로 받아와 이를 state.todos 배열에 넣고, 나머지 데이터는 스프레드 연산자를 통해 추가해 반환해줍니다.
④ DELETE 타입은 TodoItem 에서 삭제 버튼을 눌렀을 때, 해당 TodoItem 의 TodoItem 들을 구별해주는 id 값을 매개변수로 받아와 기존 todos 배열에서 map 메서드를 통해 해당 id 값이 담긴 객체를 todos 배열에서 제거하고, 새로운 배열로 담아 반환해줍니다.
⑤ Done 타입은 TodoItem 에서 완료 또는 취소 버튼을 누르면, 해당 TodoItem 의 id 값을 매개변수로 받아와 기존 todos 배열에서 map 메서드를 통해 해당 id 값이 담긴 객체의 isDone 값을 불리언 타입을 반대로 바꿔 새로운 배열로 담아 반환해줍니다.
⑥ Detail 타입은 TodoItem 에서 상세보기를 클릭할 때, 해당 TodoItem 의 id 값을 매개변수로 받아와 기존 todos 배열에서 해당 id 가 담긴 객체 하나를 detailTodos 에 선언하고, 이를 반환해줍니다.
'항해 16기 > Week I Learned' 카테고리의 다른 글
[항해 70일차] WIL_translate 를 이용한 Carousel(캐러셀) 구현 (0) | 2023.10.25 |
---|---|
[항해 63일차] WIL_React-Query 에 대해 온전한 이해 (0) | 2023.10.15 |
[항해 28일차] WIL_React 심화주차: 모달, 버튼을 포함한 웹 페이지 (0) | 2023.09.07 |
[항해 7일차] WIL_숫자야구게임 (0) | 2023.08.21 |
[항해 -1일차] WIL_1 사전 스터디(css 기초), mini 프로젝트 (0) | 2023.08.13 |