생각기록
2023-01-19 / React Redux 첫 수업/ to do list 만들기 본문
지난시간
cdl, 모듈을 가져오지 못할땐
패치 사용 추천!
(axios 와 둘다 사용할 줄 아는 것을 추천)
컴포넌트 꾸미기
styled components 라이브러리
리액트는 컴포넌트 단위 구성이고, 많아지기 쉽다. css 따로 관리하기 귀찮으니...!
소규모로 하기 좋다.
<MyDiv>
const MyDiv = styled.div` css 동일 문법 `
public 폴더
그냥 쓰면 된다.
단, 직접 웹팩을 쓰거나 리액트 프레임을 cdn으로 불러오면 사용 못함
npx ~create app 만들면 자동 설정이 되어있다.
' / ' 처리하면, 알아서 public 폴더까지 static 처리가 되어 있다.
또 한가지 차이점은
import는 src 폴더 내부까지만 import 가능! ( 보안적 이슈 때문에 막고 있음 )
props.chidren
프롭스는 워하는 데이터를 보내는것
칠드런은 html 요소를 보낼 수 있다.
리액트 router
기존 html, js 개념에서는 주소가 바뀌는것은 => 파일이 바뀌는 개념
리액트 파일은 index.html 하나 고정
주소에 따라 달라지는 컴포넌트가 변경되는 개념
사용하기 위해 모듈 설치
npm i react-router-dom
라우팅 조건 <App> 뭐로 감싸래..
처리할 주소값 = 컴포넌트 매칭

주소 예외 처리
미들웨어에서 처리하는것과 비슷
사용자가 예상치 못한 주소값 > 서비스 신뢰를 위해 예외 처리
page not found
* 는 모든 주소

코드 처리 방향

맨밑에 위치 시켜 예외 처리 가능
주소 parameter 활용

주소/:파라미터
받는것은 useParms로 받을 수 있다.
이거로 하면, 키와 아이디 값으로 된다.


리덕스
코딩애플
기존 스테이트 값을 다른 컴포로 보내려면..

보라색을 최상단까지 올리는데 고통 스럽다.

하나의 스토어란 개념 + 그곳에 상태 관리값을 넣고, 호출하는 식으로 해서 상태관리가 용이

뷰(컴포넌트)
스토어 > 스테이트값이 존재, 리듀서(조절 일꾼), 디스페처(우편 배달부)
디스페처(배달부)의 엑션(편지)을 가지고 리듀서(일꾼)에게 전달해서 리듀서가 일을 처리해서 스테이트 값이 변경되어 컴포넌트로 들어갑니다.
단방향 형태
리덕스 기초 셋팅



provider에 스토어를 제공
앱에 스토어가 언제든 접근 가능하도록 감쌋다
상태 담당 스테이트, 변경 리듀서

weight 가 state
컴포넌트에서 스토어에 저장된 상태관리 값 가져오는법
유즈셀렉터 사용

스테이트 변경을 위해
액션(행동) & 리듀서(기능)

STATE--; STATE++; 이런게 액션
dispatch 액션을 담아 잘 전달
dispatch 사용 위의 액션 객체의 type 키를 받아 전달하는 것!


살찌기 빼기는 기능
리덕스 기초 셋팅
npx create-react-app '프로젝트명'
npm i redux react-redux @reduxjs/toolkit > 모듈 한큐 설치
npm i redux
npm i react-redux
store 만들기 (구조)
- 상태를 저장할 store 부터 만들기 ( 기능 전, 저장할 공간 생성 )
- src 내부 store 폴더
- store 폴더 전체를 총괄하는 모듈은 index.js가 담당
store 전체 총괄 폴더 index.js 파일
store 모듈 분할
- 모든 컴포넌트에 대한 글로벌 상태 값을 하나의 파일에서 관리하면?
- 해당 파일이 하는 일이 많다!!
- 이것은 코드 확장성 및 관리에도 어려움이 생긴다. => 각 기능별 store 모듈을 분할 하기
백엔드에서 유저 기능, 다른 기능 분리 해둿던 것처럼
modules 폴더 안에 > todo.js 파일 만들기
redux의 목표는 상태 관리 라이브러리, 즉 관리할 상태부터 만들어야한다.
초기 state 값 선언
- 컴포넌트가 최초 랜더링 될 때 보여줘야 할 최초의 State 값 설정하기
- 물론 db에서 데이터를 받아서 설정해 주는 방법이 맞지만, 편의를 위해 변수로 설정할 예정
- todo list 이므로 객체 담긴 배열 형태 선언 예정
List 객체에는 아래의 값이 구성 될 것
- id : 고유 id 값
- text : 할 일 내용
- done: 완료 여부 (하기전, 후)
값이 잘 불러와지는지 볼까요
Reducer로 값 리턴 시키기
리듀서를 통해 State 전달!
- 설정한 State 값을 외부에서 접근 하기 위해서는 Reducer 를 통해 값을 return 시켜줘야 합니다.
- 설정한 State값을 바로 return 시켜주는 간단한 reducer를 작성해보자
위의 초기값을 State에 state 값을 리턴하는 형태로 간단히 작성
원래는 전달 된 2번째 매개 변수인 action의 type에 따라 다른 동작을 수행하는 것이 진짜 reducer입니다.
지금 초기 state 값을 외부로 전달하기 위한 목적으로 초기값을 넣어 return 한 것
Store 통합 관리
store는 모듈 별로 관리하고, 모듈 들은 store 폴더의 index.js 에 의해서 통합 관리 된다.
모듈 통합관리 방법 index.js
먼저 초기 값을 선언한 todo.js 를 import 해서 todo.js 의 reducer를 불러오기
=> export default로 설정되었다면? redux의 combinReducer를 이용하자
combinReducer을 이용하여 todo.js 의 reducer를 하나로 합쳐서 다시 내보내 준다.
*combinReducer -> reducer를 하나로 합쳐주는 기능
각각의 Reducer들을 합쳐주는
1. combinReducer 를 이용해 각각의 store 모듈에서 export 된 reducer(모듈들)를 하나로 합친다.
2. 그리고 합쳐진 reducer를 export default로 내보내 줍시다!
todo와 다른 것을 합쳐서 내보내주는 구조
Redux 기초 셋팅 및 Store 연결
Redux 기초 셋팅
라우팅 처리 하던 것처럼
redux 적용을 위해서는 <Provider> 컴포넌트 import 하고 해당 컴포넌트로 <App>컴포넌트를 감싸준다.
( * 값이 필요한곳만 감싸도 된다 )
Src 폴더의 최상위 index.js 에 가서 코드를 처리 ( Store 의 index.js 아님!!!!!!!!!!!!! )
combindeReducer 를 통해 하나로 합쳐서 내보낸 Reducer는 rootReducer라는 값으로 받아 준다
src > index.js
provider로 app 감싸기
rootReducer은 모듈 통합관리 > store/index.js 가져온 것
Todo List 의 기본이 될 컴포넌트 만들기
- 할 일 목록을 보여주고, 추가 하는 기능 컴포넌트 => TodoList
- 완료된 목록을 보여주는 컴포넌트 => DoneList
- 위의 두 컴포넌트를 '포함' 하여 전체 앱을 그려주는 컴포넌트 => ListContainer
<TodoList> 컴포넌트
할 일 추가 input 요소 / 추가 버튼 요소
할 일 목록을 redux를 통해 Store에서 받아온 다음!
해당 목록을 <ul> 태그의 <li>요소로 그리기
* 리덕스로 가져올 것
모듈화 됬던 todo.list 값
<DoneList>컴포넌트
List 는 일단 useSelector를 이용해서 State 값을 받아 온다
완료된 List를 받으면, 해당 List 를 ul 요소로 그린다.
<TodoList>에서 인풋 입력을 뺀 상태로 구현
<ListContainer>컴포넌트
이 컴포넌트는 위의 두 컴포넌트를 순서대로 포함
각각 컴포넌트 improt 한 다음 자식 요소로 만들기
리스트 컨테이너를 app.js 로 부른다
값이 들어오고 있네요 확인!
Rudux 를 위한 편의 도구
편의 도구가 왜 필요?
Redux에 저장 된 Store 의 값은 src 폴더의 index.js 파일에서 getState()메소드를 이용하여 확인 가능
지금은 간단한 TodoList 를 만들기때문에 하나의 값만을 처리 하지만, 프로젝트가 커지게 되면 다양한 전역 상태 값을
redux로 관리해야 합니다.
그럴때마다 redux 모든 값 하나하나 콘솔로 찍어가면서 확인하기 귀찮다!!
크롬 확장 도구
Redux DevTools 설치
https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=ko
사용법
사용법
코드 추가 없이도 사용 가능
redux-devtools/extension at main · reduxjs/redux-devtools (github.com)


const reduxDevTool =
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__();
const store = configureStore({ reducer: rootReducer }, reduxDevTool);

스테이트값 확인
어떤 액션?
이전 이후 어떤 값의 차이가 있는지 알 수 있다.
1. 앱으로 키는 방법
2. 도구에서 키는 방법
Action 타입 정의하기
Action 타입은 “문자열”로 보통 정의합니다!
Todo 리스트에 필요한 생성, 완료 액션을 정의합시다!
create / done 만 있으면 될 것 같다!
앞에 todo/ 는 왜 붙이는 건가요?
모듈이 달라도 Action 타입으로 CREATE, DELETE, DONE 같은 변수명은 상당히 많이 사용이 됩니다
그럴 때 잘못 된 모듈 Import 로 인해, 다른 Reducer 의 기능이 호출되면 문제가 발생합니다
이럴 때 Action 타입 앞에 지금 이 액션의 타입이 어떤 모듈의 타입인지를 알려주는 문자열을 추가하여 위와 같은 문제가 발생하는 것을 막아 줍니다!
메뉴표를 만들었다
이젠 어떤일을 해야할지 정해줘야하는데 그것이 action 입니다.
Action 생성 함수 작성
외부 컴포넌트에서 action 을 만들어주는 함수부터 작성
Action 생성 함수는 type 정보와 전달해야 할 정보를 payload 객체에 담아 서 Dispatch 를 통해 전달 합니다
결과적으로 Reducer 가 Action 함수에 들어있는 type 을 확인해서 어떤 행동을 할지 정하고,
payload 에 있는 데이터를 받아서 처리 합니다
payload > 어떤 일을 할 건지의 데이터가 여기 들어갑니다. ( 컴포넌트에서 리덕스에 데이터를 보낼게 있다는 뜻!!)
DONE 액션 생성 함수도 만든다.
컴포넌트에서 데이터를 보내게 되는 일이 생긴다.
나르는 역할을 payload가 하게 된다.
외부에서 값을 변경해서 버그가 나는 일을 막는다.
발생해도 스토어 내부에 있는 얘들만 수정하면 되도록 구조를 짬
Reducer 구조 구현
Action type 에 따라 작동하는 Reducer
이제는 Action type 에 따라 작동하는 Reducer를 구현해 봅시다.
먼저 Switch 문을 이용해서 action type 에 따라서 각각의 역할을 한 뒤 값을 return 하는 구조로 만들어 준다.
스위치는 default가 있어야함
여기까지 리듀서
디스패치에 이 액션생성함수를 전달!
컨테이너 컴포넌트에서 인풋값이 스토어까지 가야한다.
가방이 리듀서로 들어오게해서 여러 일을 하게 한다.
payload 열어서 확인
Dispatch 로 Action 함수 전달
그럼 이번에는 컴포넌트에서 Dispatch 로 정의한 Action 함수를 Reducer 에 전달하여
정상적으로 호출이 되는지 확인해 봅시다!
Dispatch 활용을 위해 useDispatch 를 dispatch 변수에 넣어주기!
Src/store/modules/todo.js 에서 create, done 함수 불러오기!
Dispatch 의 인자로 create, done 함수를 전달하여 호출 상태 확인
todo의 리듀서에 있는 함수들을 모듈처럼 가져와서 쓰고 있다.
todo 의 액션 생성 함수 create 를 dispatch에 인자로 받고 있다!!
추가버튼을 누르게되면,
페이로드를 넣어주진 않았지만
콘솔이 찍히는 걸 볼 수 있다.
에러? > state 반환을 안해줘서 뜨는 것 (콘솔만 찍어놔서)....
Reducer 의 CREATE 동작 구현
이제 들어온 Action Type 에 따른 reducer 의 실제 동작을 구현해 봅시다!
혹시 모를 다른 초기 값이 있을지 모르므로 state 를 전개 연산자로 먼저 리턴해 줍니다.
List 의 경우는 새롭게 입력 받은 값을 list 의 배열에 넣어 주면 됩니다
주의 할점 ! / 왜 전개연산자를 쓰나요?
지금은 리스트밖에 없지만 만약
유저, 맴버가 있다.
전부 명시하지 않으면, 나머지 들은 사라지게 된다.
그것을 쉽게 처리하는게 위에 ...state 입니다 !
변경하고 싶은 값만 뒤에 빼줍니다. 모든 값을 return 해준다.
nextID : a~ + 1 xxxx잘못된 코드임!! 지울것
push로 하면 숫자값이 들어가게 된다.,
우리는 배열을 리턴해야 한다.
concat은 해당값을 추가하고 마지막 부분에 추가된 배열을 추가해서 전체를 리턴합니다.
원본배열에 뭔가 추가할때는 둘다 상관없지만, 지금 배열을 리턴 해야하기 때문에 concat을 씁니다.
Dispatch 로 CREATE 호출
CREATE 호출
이번에는 CREATE 의 함수에 제대로 된 인자를 전달하여 정상적으로 기능 이 작동하도록 해봅시다!
리듀서에서 할 일 목록 추가로 필요한 정보는 id 값과 새롭게 추가될 할 일의 text 값이 필요합니다
→ 두 데이터를 객체에 담아서 인자로 전달해 봅시다
디스패치(우편배달부)가 액션생성함수(가방)을 들고 리듀서에게로 갑니다.
클라이언트의 데이터가 필요하니 배달부인 디스패치가 컴포넌트에서 쓰이게 됩니다.
필요한 데이터는 id, text 키와 값으로 객체 형태로 보냇다.
Reducer 의 DONE 동작 구현
동일하게 list 이외의 초기 state 값은 그대로 전달이 되어야 하므로 전개 연산자를 사용!
List 의 경우는 컴포넌트에서 전달 받은 id 값과 동일한 객체를 찾은 다음
=> 해당 객체의 done 항목을 true 로 변경하면 됩니다!
이럴 때는 map() 을 쓰면 편합니다!
map() 은 배열의 모든 값을 순회 하면 서 배열의 값을 return 된 값으로 변경해 줍니다
전개연산자, map 사용
리듀서 설정이 끝나면,
Dispatch로 DONE 호출!
이번에는 DONE 함수에 제대로 된 인자를 전달해 정상적 기능이 작동하도록 해봅시다
리듀서에서 완료 된 목록의 ID값만 받아서 해당 목록의 done 항목을 true 로 변경하면 된다.
TodoList.jsx
dispatch에 액션모듈넣고 그 인자에 보낼 값을 넣는다.
보니까.. 완료 목록과 할일 목록 리스트가 동일하다.
각각 컴포넌트에 Filter 걸기
필터 처리
지금 <TodoList>, <DoneList> 컴포넌트는 동일한 리스트 출력 중!
이제 done의 값을 통해 필터링 하여 <TodoList>에는 할일 목록만,
<DoneList>에는 완료된 목록만 남겨보자
필터를 씌워야한다
완료된 얘들은 할 일 목록에 없도록 list 받아올때 필터 걸면 된다.
<TodoList> false값만 받아오고
<DoneList> 는 true 값만 받아오게 필터 설정!
리듀서 함수인데
1. 생성시 done에 false값을 넣고있다. / 완료 버튼을 누르면 done이 true가 된다.
2. todolist 컴포넌트에서는 이 값을 필터함수로 el(요소).done 의 키 값이 false 인 얘들만 출력시킨다.
필터를 걸어주고나서
테스트 해보면,
오류 > 키값이 동일해서 생기는 오류
우리가 todolist의 저부분과 donelist에 key값과 겹쳐서 나는 오류!
해결방법
할 일 목록의 id를 목록의 순번으로 부여를 하고 있으므로, 해당 순번도 store 에서 전역으로 관리하는 문제를 막자
- ID 를 관리하기 위한 State 생성!
- Store 의 todo 모듈에 ID 관리를 위한 값을 설정해 봅시다!
- 일단 초기 List 의 길이 값을 구하고, 해당 값을 다음에 생성 될 할 일 목록의 ID 값으로 넘겨주는 구조를 그려 봅시다
mysql에 프라이머리 키하는 방식으로 만들어보겟다.
todo.js
초기값과 리듀서를 설정이 끝났으니
이제 영향을 받는 컴포넌트로 갑니다.
받는곳도 수정해야 하니까요
<TOdoList > 컴포넌트
되네요!!!
리덕스 동작 순서
1. 스토어 세팅
- 폴더 안에 모듈스
- 혹시나 다른 상태를 관리하기위한 모듈스폴더
- todo 상태관리 스토어 만듬
2. 그안에 초기값 설정
- todo 상태관리 스토어 만든곳에 초기값
- 그리고 상태 만들기
3. 리듀서 고용 (우체국)
- 리턴하나만 만듬 (연결 확인용)
- 모듈들을 하나로 합치는 store > indext.js 에 combinReducer 사용해서 합친다.
- APP이라는 컴포넌트가 쓰니까
- SRC 의 INDE.JS에서 합친얘를 루트리듀서로 임포트 하고 Provider로 감싼다.
- 프로바이더에 store 선언해줌
여기까지가 기초셋팅 > 나중에 reducer 리턴하는것만 달라진다.
4. 액션 타입 정의 (편지)
CREATE, DONE
5. 액션 함수 설정 (가방)
액션 타입을 담을 가방이다.
Payload인자에 데이터를 담는다. ( 어떤일을 하는 데 쓰일 재료 )
액션 타입을 실행할때 외부에서 가져다 쓰도록 export 펑션 함수 형태로 지정 해둠
6. 리듀서 case 문으로 return 값들 변경해주기
액션 타입에 맞게 어떤일을 해야하는지 선언해줘야 한다.
키값이 겹치는 오류가 생기면,
7. 디스패치로 action 함수 전달 > (우편배달부)
우편배달부는 가방을(액션생성함수)들고 리듀서(우체국)를 호출한다
프론트에서 받은 값을 / 가방에 payload 를 열어서 리듀서에게 전달한다.
리듀서는 액션타입에 맞게 편지지를 조리하고 state값을 변경한다.
'강의 정리 > React JS' 카테고리의 다른 글
2023-01-26 순수 리덕스 과정 (0) | 2023.01.26 |
---|---|
2023-01-19 / 개발자 MBTI 조사 / React Redux (0) | 2023.01.19 |
구조 분해 할당 (0) | 2023.01.18 |
2023-01-17 React Router, redux (0) | 2023.01.17 |
2023-01-17 useEffect실전, public 폴더 사용, props.children 이란? (0) | 2023.01.17 |