11월 21일 (화) redux (action, store, reducer)

남이섬·2021년 11월 21일
0

Action

Action은 말 그대로 어떤 액션을 취할 것인지 정의해 놓은 객체다

ex
{ type: ‘ADD_TO_CART’, payload: request }

보통 위와 같은 모양으로 구성된다
여기서 type 은 필수로 지정을 해 주어야 하며, 그 외의 것들은 선택적으로 사용할 수 있다

이렇게 모든 변화를 action을 통해 취하는 것은 내가가 만드는 앱에서 무슨 일이 일어나고 있는지 직관적으로 알기 쉽게 하는 역할을 한다

actions > index.js 파일에서는 action들을 구성한다

Dispatch

Dispatch는 Action을 전달하는 메소드다

dispatch의 전달인자로 Action 객체가 전달된다, 그리고 Reducer를 호출해 state의 값을 바꾸는 역할을 한다

Store

state가 관리되는 오직 하나뿐인 저장소의 역할을 한다

Redux 앱의 state가 저장되어 있는 공간이다

const store = createStore(rootReducer);

다음은 createStore 메소드를 활용해 reducer를 연결하는 방법이다
createStore와 더불어 다른 리듀서의 조합을 인자로 넣어서 스토어를 생성할 수 있다
(실제 소스 코드에서는 미들웨어와 Redux devtools 지원을 위해 두번째 인자에 추가적인 내용이 들어가있다)

store > store.js 파일에서 createStore 메소드를 활용해 rootReducer를 연결 해 주고 있다

Reducer

Reducer 는 현재의 state와 Action을 이용해서 새로운 state를 만들어 내는 pure function 이다

pure function
순수 함수 에는 네트워크 요청과 같은 Side Effect가 없다
순수 함수의 특징 중 하나는, 어떠한 전달 인자가 주어질 경우, 항상 똑같은 값이 리턴됨을 보장한다
그래서 예측 가능한 함수이기도 하다

ex market 장바구니 추가 액션 코드

const itemReducer = (state = initialState, action) => {
  switch (action.type) {
    case ADD_TO_CART:
      return Object.assign({}, state, {
        cartItems: [...state.cartItems, action.payload]
      })
    default:
      return state;
  }
}

witch문을 통해서 코드를 작성했지만 if문으로 작성해도 무방하다

Reducer의 Immutability(불변성)

Reducer 함수를 작성할 때 주의해야 할 점이 있다
바로 Redux의 state 업데이트는 immutable(불변)한 방식으로 변경해야 한다는 것이다

Redux의 장점 중 하나인 변경된 state를 로그로 남기기 위해서 꼭 필요한 작업이다

(React에서 state를 변경하기 위해서는 this.state에 바로 할당하는 것이 아닌 this.setState를 통해 state를 변경해주어야 한다)

React life cycle
리엑트에서는 가상돔을 사용하고있으며, 가상돔에서는 state를 직접적으로 변경하게 되면 변경이 됐는지 인지를 못한다 그래서 setState 함수나, useState의 set함수로 변경을 해줘야 가상돔에서 인지하고 돔으로 변경된 사항을 돔으로 전달을 해준다
react life cycle 공식 문서

side effect
React 컴포넌트가 화면에 렌더링된 이후에 비동기로 처리되어야 하는 부수적인 효과들을 흔히 Side Effect라고 일컽는다
대표적인 예로 어떤 데이터를 가져오기 위해서 외부 API를 호출하는 경우,
1. 일단 화면에 렌더링할 수 있는 것은 먼저 렌더링하고,
2. 실제 데이터는 비동기로 가져오는 것이 권장된다
요청 즉시 1차 렌더링을 함으로써 연동하는 API가 응답이 늦어지거나 응답이 없을 경우에도 영향을 최소화 시킬 수 있어서 사용자 경험 측면에서 유리하기 때문이다

React Hooks가 나오기 전에는 클래스 컴포넌트의 componentDidMount()componentDidUpdate() 함수와 같은 Life Cycle Hook 함수를 사용해서 Side Effect 처리했었다

useEffect
함수형 컴포넌트에서는 useEffect Hook을 사용하면 side effect를 수행하는게 가능하다
첫번째 인자로 오는 함수(effect)를 React는 기억하는데 DOM을 업데이트 하고 난 후에 이 effect를 수행하며, 기본적으로는 첫 렌더링과 그 이후의 모든 업데이트에 대해서 effect를 수행하게 된다
(useEffect Hook을 componentDidMount와 componentDidUpdate, componentWillUnmount가 합쳐진 것으로 생각해도 좋다)
useEffect 공식문서

그렇다면 immutable한 방식으로 state를 변경하기 위해서는 어떻게 코드를 작성해야 할까?
위의 itemReducer 예제 코드에서 Object.assign을 통해 새로운 객체를 만들어 리턴하는 것을 통해 힌트를 얻을 수 있다

Object.assign()
Object.assign() 메서드는 출처 객체들의 모든 열거 가능한 자체 속성을 복사해 대상 객체에 붙여넣습니다. 그 후 대상 객체를 반환한다
Object.assign mdn

그렇다면 reducers > index.js 파일에서 rootReducer를 구성할 차례다
Reducer은 combineReducers 메소드를 통해 여러 가지의 Reducer들을 하나로 합칠 수 있다

connect 할 수 있는 방법은 두 가지가 있다

공식 문서를 통해서도 확인하실 수 있듯이 connect parameter를 통해 mapStateToProps, mapDispatchToProps 등 의 메소드를 이용하는 방법과 Redux hooks를 이용하는 방법이 있다

Redux hooks에서는 크게useSelector(), useDispatch() 이 2가지의 메소드를 기억하면된다

useSelector()

useSelector()는 컴포넌트와 state를 연결하는 역할을 한다
컴포넌트에서 useSelector 메소드를 통해 store의 state에 접근할 수 있다

useSelector의 전달인자로는 콜백 함수를 받으며, 콜백 함수의 전달인자로는 state 값이 들어간다

useDispatch()

useDispatch()는 Action 객체를 Reducer로 전달해주는 메소드다
Action 이 일어날만한 곳은 클릭 등의 이벤트가 일어나는 컴포넌트다

redux 공식문서

profile
즐겁게 살자

0개의 댓글