raycon / til

Today I Learned
MIT License
16 stars 3 forks source link

Redux #25

Open raycon opened 3 years ago

raycon commented 3 years ago

Redux

무슨 Re- 가 이렇게 많냐...

React: 각각의 Component 혹은, 공통된 부모가 state를 관리합니다. Redux: Store를 하나 만들어서 state를 관리합니다.

Concepts

Action ---> Reducer ---> Store(state)

Store

Store는 state를 관리합니다. 특정 Action이 발생할 경우, Reducer로 이를 처리합니다. 이를 위해 Store를 생성할 때, Reducer를 전달해야 합니다. Reducer를 여러개 사용하기 위해서는 Redux가 제공하는 combineReducers를 사용합니다.

Store는 Redux를 사용하는 어플리케이션에서 하나만 사용할 수 있습니다.

Action

Action은 { type: "SOME_TYPE", someKey: "SOME_VALUE" } 형태의 JSON 객체를 의미합니다. 이런 객체를 생성하는 함수를 여러개 정의해서 사용합니다.

Dispatch

Store에 정의된 dispatch 함수는 특정 Action을 Store로 전달 합니다.

Reducer

Reducer는 현재 Store의 state와 전달 받은 action을 조합해서 새로운 state를 만들어 냅니다.

Store 생성

기본 생성

import { createStore } from 'redux'
import rootReducer from './reducer'
const store = createStore(rootReducer)
export default store

초기 상태 지정

import { createStore } from 'redux'
import rootReducer from './reducer'

let preloadedState
const persistedTodosString = localStorage.getItem('todos')

if (persistedTodosString) {
  preloadedState = {
    todos: JSON.parse(persistedTodosString)
  }
}

const store = createStore(rootReducer, preloadedState)

Enhancer 지정

Enhancer : Store를 감싸서 새로운 기능을 제공합니다. dispath, getState, subscribe 메소드를 재정의 할 수 있습니다.

import { createStore, compose } from 'redux'
import rootReducer from './reducer'
import {
  sayHiOnDispatch,
  includeMeaningOfLife
} from './exampleAddons/enhancers'

const composedEnhancer = compose(sayHiOnDispatch, includeMeaningOfLife)

const store = createStore(rootReducer, undefined, composedEnhancer)

export default store

react-redux

react-reduxProvider, useSelector, useDispatch 등의 기능을 제공해준다.

Middleware

Redux middleware provides a third-party extension point between dispatching an action, and the moment it reaches the reducer.

Middleware는 dispatch 동작을 맞춤화(customize) 하기 위해 사용합니다. Action이 Reducer에 전달되기 전에 사전에 지정된 작업을 수행합니다.

Action ---> Middleware ---> Reducer ---> Store(state)

Redux의 Middleware는 Store Enhancer의 구현체입니다. 따라서 다음과 같이 스토어를 생성할 때 middleware를 Enhancer로 전달할 수 있습니다.

import { createStore, applyMiddleware } from 'redux'
import rootReducer from './reducer'
import { print1, print2, print3 } from './exampleAddons/middleware'

const middlewareEnhancer = applyMiddleware(print1, print2, print3)

// Pass enhancer as the second arg, since there's no preloadedState
const store = createStore(rootReducer, middlewareEnhancer)

export default store

Middleware는 다음과 같이 정의할 수 있습니다.

const loggerMiddleware = storeAPI => next => action => {
  console.log('dispatching', action)
  let result = next(action)
  console.log('next state', storeAPI.getState())
  return result
}

Redux Persist

Redux의 Store는 앱을 종료하면 사라집니다. Store를 저장하기 위해 Redux Persist를 사용합니다.

persistReducer, persistStore를 사용합니다 다음과 같이 사용합니다.

// configureStore.js

import { createStore } from 'redux'
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage' // defaults to localStorage for web

import rootReducer from './reducers'

const persistConfig = {
  key: 'root',
  storage,
}

// rootReducer를 감싸는 persistReducer 생성
const persistedReducer = persistReducer(persistConfig, rootReducer)

export default () => {
  let store = createStore(persistedReducer)
  // store를 감싸는 persistor 생성
  let persistor = persistStore(store)
  return { store, persistor }
}

이렇게 생성된 storepersistor를 각각 react-reduxProviderredux-persistPersistGate에 전달합니다.

import { PersistGate } from 'redux-persist/integration/react'

// ... normal setup, create store and persistor, import components etc.

const App = () => {
  return (
    <Provider store={store}>
      <PersistGate loading={null} persistor={persistor}>
        <RootComponent />
      </PersistGate>
    </Provider>
  );
};

Redux i18n

다국어를 지원하기 위한 모듈입니다. 현재 언어 설정을 저장하기 위해 redux store를 사용합니다.

공식 문서 참고

Redux Saga

특정 Action이 발생했을 때 원하는 동작을 실행시켜주는 미들웨어 입니다. Generator문법을 사용합니다.

raycon commented 3 years ago