20210627 TIL

Breadman·2021년 6월 28일
0

항해99

목록 보기
16/28
post-thumbnail

Redux

state를 전역적으로 관리하고 사용할 수 있게 해주는 툴.

state를 전역적으로 사용할 수 있게 해주기 때문에, 말단의 자식이 필요한 state를 타고 타고 타고 들어가서 전달할 필요가 없어진다.

Redux에는 총 5가지의 개념이 있다.

  • Action
  • Action Creator
  • Reducer
  • Store
  • Dispatch

흐름은 다음과 같다.

  1. Action Creator를 이용해 Action 생성.
  2. Dispatch를 이용해 Action을 Reducer에 전달.
  3. Reducer는 전달받은 Action의 Type에 따라 store 안에 있는 state 처리 진행.

Action, Action Creator

Action은 state에 처리해야할 명령이다. Action Type과 필요한 데이터로 구성된 Dictionary 형태로 되어있다. 이는 Action Creator를 이용해 만들어진다.

state는 반드시 Action을 통해 처리가 이루어져야한다.

// Action Type
const LOAD = 'myApp/LOAD';
const CREATE = 'myApp/CREATE';

// Action Creator
export const loadData = () => {
  return { type: LOAD }
}

export const createData = (data) => {
  return { type: CREATE, data }
}

Reducer

Action Type에 따른 분기를 통해 store에 실질적인 조치를 취하는 함수이다. Reducer는 반드시,

1) 입력값이 변하지 않으면 출력값도 변하지 않고,
2) 인자 외의 값에 의존해선 안되며,
3) 이전 상태를 수정하지 않고 새로운 객체를 반환하는

순수한 함수여야 한다.

const reducer = (
  state = {/* 초기값이 있으면 대체될 수 있다 */}, 
  action = {}
) => {
  switch(action.type) {
    case LOAD:
      return state;
    case CREATE:
      ...
    default:
      return state;
  }
}

Store

state가 저장되는 저장소다. 앞서 설명한대로 반드시 action을 통해 관리되어야한다. 또한 하나의 프로젝트에 하나의 store만 사용해야한다는, 단일 store 규칙이 존재한다.createStore()를 이용해 생성하고, 해당 함수의 인자로 reducer가 들어간다. 인자로 단 하나의 reducer만을 받기 때문에 combineReducers()함수를 이용해 여러 reducer를 하나의 reducer 다발로 만들어줘야한다.

import { createStore, combineReducers } from 'redux';
import aReducer from 'a-module';
import bReducer from 'b-module';

const reducers = combineReducers({ aReducer, bReducer });

export default const store = createStore(reducers);

Dispatch

state를 사용하는 파트에서 Action을 생성하고, 생성된 Action을 Reducer에 전달하는 함수다. 사용방법은 class component와 function component로 구분된다(정확히는 hook을 사용하는 방법과 그렇지 않은 방법으로 구분된다).

// class component
import { loadData, createData } from 'dataModule';
import { connect } from 'react-redux'

const mapStateToProps = (state) => (
  { dataList: stack.moduleName.dataName }
  // reducer의 switch-case에서 default를 해주지 않으면, 이 부분에서 에러가 발생함.
);

const mapDispatchToProps = (dispatch) => (
  load: () => dispatch(loadData()),
  create: (data) => dispatch(createData(data))
)

class App extends React.Component {
  ...
}

export default connect(
  mapStateTopProps, mapDispatchToProps
)(App);

// function component
import { loadData, createData } from 'dataModule';
import { useSelector } from 'react'

const App = () => {
  ...
  const dispatch = useSelector();
  ...
  <button
    onClick={() => dispatch(createData(value))}
    ...
   />
  ...
profile
빵돌입니다. 빵 좋아합니다.

0개의 댓글