Redux 강의 정리
Redux 1
- React 에서 component communication 을 배웠음. 데이터를 변경시키려면 props 를 전달, 전달하는 구조
- 문제점이 중간에 있는 component 들은 전달만 하는 component 로 사용된다는 것
이런 문제의 해결을 위해 Context API 를 사용할 수 있음
Context 를 사용할 경우, Context 가 가진 전역 data 를 잘 활용하는 게 중요함. Context 에 주어지는 전역 data 를 어떻게 효과적으로 관리할 것인지에 대한 라이브러리 = Redux
Redux 가 사용하는 방식은? 파란공 자리에 STORE
- STORE 안에 있는 상태를 보라색 공이 변경할 수 있고, STORE 의 상태를 가진 component 들이 STORE 의 상태가 변경되면 자동으로 다시 render 됨
- 보라색 공이 STORE 안의 상태를 변경하고, STORE 안의 상태를 받아서 표현하는 애들이 있는 것
어떻게 STORE 의 상태를 변경하고, 어떻게 STORE 의 상태를 받아서 render 하는 것인가? action, Reducers 부분에서 설명할 것임
*중요한 건 단일 스토어. 스토어는 1개 뿐임
- 단일 STORE 를 만드는 법, 그리고 파란선과 보라색 공이 어떻게 연결되는지가 중요하겠죠
- connect 라는 HOC 함수를 통해 컴포넌트에 연결하거나, Hook 들을 이용해 connect 역할을 대체할 수도 있음
Action
Action 은 그냥 객체. 그냥 일반 Object. 2개 형태의 Action 이 있음.
① type 이라는 property 만 가진 Action, ② type 이 있고, 그 외에 payload, 즉 다른 여러 property 가 있는 Action
type 만 필수 property 이고, type 은 보통 문자열임
이렇게 만들어진 Action 이 Store 에 전달되면 Store 에 있는 상태를 변경하는 용도로 사용됨
Store 의 상태를 변경할 때, 특별한 인자값이 없는 경우 type 만 있는 Action 이 전달되고,
Action 을 전달하면서 값을 이용해서 상태를 변경해야 한다면, type 을 제외하고 다른 parameter 도 들어가게 됨
Action 객체를 만들 때는 Literal 로 사용하는 게 아니라, Action 을 생성하는 함수를 만들어서 사용하게 됨
이런 함수를 Action 생성자라고 하고, return 은 Action 임
return 은 앞에서 배운 Action 의 형태를 띄고 있어야 하고, Action 종류별로 같은 갯수의 Action 생성함수가 만들어짐
Redux 에서 Action 은 어떤 일을 하나?
만들어낸 Action 객체를 Redux Store 에 보냄. 보내는 것은 Action, 도착지는 Store. Redux Store 는 Action 객체를 받으면, 원래 가지고 있던 상태값이 변경됨. 이에 따라 상태를 이용하고 있는 component 가 변경됨. Component 와 Redux store 는 연결되어 있으니까, Action 이 component 를 변경하는 요인이 됨
Action 준비? 2단계
- Action type 을 정의하고, 상수로 빼둔다. type 이 문자열이니까 실수 방지를 위해
- Action 생성함수를 만든다. Action type 은 위에서 정의한 type 상수로 부터 가져와서 사용한다
Reducer
Action 을 주면 그 Action 이 적용돼서 달라진/안 달라진 결과를 만들어주는 "함수"
함수인데, PURE Function. 항상 같은 input 을 받아서 같은 output 을 내는 함수. Reducer 안에 시간에 따라 다른 결과를 낸다든지 하는 형태의 코드가 들어가면 안됨
Immutable 해야 함. Original State 와 New State 가 별도의 객체로 만들어져야 한다, 서로 다른 참조를 가져야 한다 (Redux 가 state 의 변경을 인지하는 방식)
Reducer 란 이름이고, 1번째 인자는 previousState (현재 State), 2번째 인자는 Action 객체
previousState, Action 객체를 이용해서 새로운 State 객체를 만들어 냄. Action 을 받아서 State 를 리턴하는 구조
Reducer 를 작성할 때는 State 의 모습에 대해 구상해 봐야 함
최초에 Reducer 가 어디서 실행됐을 때는, 현재 previousState 가 뭔지 설정해줘야 함. 아무것도 지정이 안 돼 있다면, 가장 최초의 상태일 것임. 그래서 초기값을 지정해줄 수 있음
아무 대응도 하지 않는 경우, 똑같은 State 를 리턴하면, Immutable 하지 않음. previousState.push(); 같은 메소드는 객체는 변경하지만, 객체의 참조는 변경하지 않으므로 사용하면 안됨
const initialState = 초기값 상태를 먼저 정의해주고, 미리 지정해주면, 가능
Reducer 를 Pure 하게 만들고, Immutable 하게 처리되게 만들 작성이 끝남
Reducers in Redux
Redux 라이브러리를 이용해 createStore 함수를 활용하자. Redux 에서 가져와서 사용하고, Store 를 만드는 함수
Store 를 만들면, Store 안에 있는 상태와, 상태를 변경하는 Action 을 보내서, 각종 State 관리를 할 수 있음
createStore 함수의 인자는 3개
① Reducer 함수, ② preloadedState (initialState 를 넣거나 Reducer 에서 처리), ③ enhancer
reducer 만 넣어서 createStore 하고, Store 에 어떤 게 들어있나 console 에 찍어보면
dispatch, getState, replaceReducer, subscribe 4개 정도의 함수가 들어있음
store.getState 하면 현재의 상태가 출력됨. 최초에 [] 나오는 것은 preloadedState 를 설정하지 않았지만, Reducer 에서 initialState 를 지정했으므로 그게 출력되는 것
Store 의 상태를 이제 변화시킬 건데, Action 을 인자로 가지는 함수가 Dispatch. React hook 에서 useReducer Hook 을 사용할 때도 사용한 함수, dispatch 를 사용해서 action 을 던지면 state 가 변경되었음
store.dispatch 하고 Action 객체를 넣으면 되는데, Literal 로 작성({ type: xx }) 이 아니라, Action 생성함수를 이용함
넘기는 인자를 "todo" 로 보내면, Action 이 생성돼서, Dispatch 가 날아가고, Store 에 도착하고, State 를 변경함
다음 줄에서 store.getState() 하면 결과가 바뀌어 있음
이 코드를 Store 의 Subscribe 함수를 활용하겠음 (= 구독하다)
Store 에 변경사항이 생기는 것을 구독하는 것. 함수를 넣으면, Store 의 상태가 변경될 때마다 구독한 함수가 호출됨
getState 출력을 넣으면, 구독 시작했으니까 dispatch 하면 subscribe 이 실행되면서 결과가 나옴
구독해 놓으면 dispatch 가 일어날 때마다 subscribe 내부에 인자로 넣어준 함수가 계속 호출됨
subscribe 의 리턴함수는 unsubscribe 함수임. 어떤 시점 후에 unsubscribe 를 호출하면 그 후에는 똑같이 dispatch 해도 구독함수 호출이 안됨. 실제 Store 에는 변경이 진행돼 있음
getState : 현재 Store 의 state 를 가져오는 함수
dispatch : Action 을 인자로 넣어서 Store 상태를 변경시키는 함수
subscribe : Store 에 변경이 생겼을 때 특정 함수를 실행하도록 하는 함수, 결과물이 unsubscribe 역할을 하는 함수. unsubscribe 호출하면 구독함수가 제거됨
replaceRudcer : 원래 가지고 있던 Reducer 를 다른 Reducer 로 바꾸는 것인데, 실무에서는 잘 안쓰임
combineReducers
Store 가 커질 때, Store 안에 있는 State 가 복잡해질 때 어떻게 처리하는 지를 배워보겠음
기존 Reducers 에 initialState 를 ["코딩", "점심 먹기"] 에서 [{ text: '코딩', done: false}, { text: '점심 먹기', done: false}] 로 바꾸면서 done: false -> true 로 complete 처리해주는 Action 을 추가함
추가로 Store 안의 상태 중에 현재 View 에서 어떤 걸 보여줄지를 필터링하는 property 를 하나 더 추가하면 initialState 가 객체가 됨 {todos: [{ text: '코딩', done: false}, { text: '점심 먹기', done: false}], filter: 'ALL'}
Reducers 안에 있는 로직이 App state 가 커질수록 복잡해짐
Redux 는 단일 Store 임. Reducer 안에 있는 내용을 쪼개는 능력이 필요함
Action 종류에 따라, ① Todo 에만 영향 O Filter 에는 영향 X ② Todo 에는 영향 X Filter 에만 영향 O
이렇게 별개의 Reducer 로 작성해서 하나로 합치는 식으로 로직/파일을 쪼개는데, 이를 combineReducer 로 구현가능
*패스트 캠퍼스 프론트엔드 강의를 듣고 정리함