React-Redux

Huge App

Day-5-Starting-Point

복잡한 App, 여기저기서 사용되는 state.value

🤷🏾‍♂️

Flux Pattern

React-Redux

Flux와는 비슷하면서도 조금 다른 개념

One State, One Tree

그럼 모든 local한 state들은 필요가 없어지는 것일까요?

단순하면 단순할 수록 좋다

지금 우리가 만든 Component의 구조는

API 요청도 많았고

Lifecycle Hook도 많이 사용했고

Method도 많이 만들어 사용했고

최대한 한 군데 모아놓고 Component들은 필요한 props만 받아서 쓰는 것 🙌🏽

React의 역설

Redux 👉🏿 Reducer

Reduce(a, b) => c

HugeAppState = {

  rootColor: red

}

HugeAppState.rootColor = blue

State

Reducer(HugeAppState, action) => NextHugeAppState

Reducer(state, action) => nextState

View: this.render

Store: this.state

Action: this.handleChange

Dispatcher: this.setState

장점들

  • 직접 바뀔일이 없다 => 에러 발생할 여지 적다
  • action이 들어올때 마다 새로운 state가 생긴다
  • 기존 State들을 보존하면 => 시간 여행 가능
const state = [
  'React 복습',
  '수업내용 정리',
  '밥 먹기',
]

const reducer = (state, action) => {
  if (action.type === ADD_TODO_LIST_ITEM) {
    return {
      ...state,
      action.item,
    }
  }
}


nextState = reducer(state, { type: ADD_TODO_LIST_ITEM, data: '영화보기'})

reducer()는?

Reducer(state, action) => nextState

기존의 방식

Event 발생

=>

Handler 호출

=> 

this.setState()

=>

this.render()

리덕스의 방식

Event발생(액션 발생)

=> 

Handler 호출(액션 Dispatch)

=>

reducer() 

=> 

관련 컴포넌트들 this.render

버튼 클릭 => Action 발생

state

nextState

action = { type: 'CLICK', payload: '...' }

store.dispatch(action)

reducer(state, action)

store

store는 state의 매니져

store에서 사용하는 method

getState()

dispatch()

프로덕트를 만들 수 있다

좋은 프로턱트를 만들 수 있다

실습 시간

store, getState, dispatch

actionCreators, actions

reducers, createStore

Provider, connect

mapStateToProps, mapDispatchToProps

Redux Ecosystem

  • Redux-Logger
  • Redux-Thunk
  • 그 외에도 다수

actionCreators => action

OX Quiz:

actionCreator는 한 종류의 action만 만들어야한다

Redux Logger

  • Action과 Store의 State 변화를 로깅해서 보여주는 미들웨어

비동기 actionCreator

ActionCreator: Action을 주고 싶은데 fetch가 비동기라 바로 줄수가 없네 

Store: dispatch 줄테니깐 준비되면 이 dispatch로 action불러

Redux의 작동 체계를 아는 우리

nextState = reducer(currentState, action) => {

  if (action.type === 'ACTION_ONE') {

    return { ...state }

  }

  return { ...state }

}

Redux-Thunk

reducer(currentState, action) => nextState

syncAction😏 => syncAction😏 => syncAction😏 => asyncAction😲=> syncAction😏

store🤓

const asyncActionCreator = (param) => {
  return (dispatch) => {
    dispatch() // 어떤 액션?
    return fetch(param.URL)
      .then((resp) => resp.json())
      .then((responseData) => {
        dispatch(action); // 어떤 액션?
      })
      .catch((error) => {
        dispatch()  // 어떤 액션?
      })
  }
}

새로운 사실

if (action is Object) {

  this.dispatch(action)
} else if (action is Function) {

  action(this.dispatch)

}

npm intall --save redux-logger

npm install --save redux-thunk

Redux 자체는 매우 가볍

위의 Middleware들을 추가해보겠습니다

실습

const createStoreWithMiddleware = applyMiddleware(logger, thunk, ... )(createStore)

 

const store = createStoreWithMiddleware(reducers)

store = createStore(reducer)

전형적인 API요청에서는 어떤 Action들이 필요할까요?

Hint: WordLists 컴포넌트에서의 예외 케이스들

Error, isLoading

우리의 WordList 페이지를 Redux State를 이용하도록 바꿔보겠습니다

Caching

GET_WORD_LIST_REQUEST

GET_WORD_LIST_SUCCESS

GET_WORD_LIST_FAILED

 

const store = {
  isLoading: false,
  wordLists: [],
  selectedWordList: {id: 4, title: 'abc', ...},
}

const fetchWordsFromWordListId = (id) => {
  return (dispatch) => {
    dispatch({ type: 'IS_LOADING' })
    fetch(generateURL(id))
      .then()
      .then(() => dispatch({ type: 'SUCCESS'}))
      .catch(() => dispatch({ type: 'FAIL'}))
  }
}

성능 좋은 프런트엔드

최소한의 API 요청

Testing,

Server Side Rendering,

Code Splitting,

Build / Development Mode,

Flow Type Checking,

Service Workers,

React 개발자의 고민

const store = {
  isLoading: false,
  wordLists: [],
  selectedWordList: {id: 4, title: 'abc', ...},
  cachedWordList: [],
}
const fetchWordsFromWordListId = (id) => {
  return (dispatch) => {
    if (id is in cachedWordList) {
      return dispatch({ type: 'SUCCESS'})
    } else {
      dispatch({ type: 'IS_LOADING' })
      fetch(generateURL(id))
        .then()
        .then(() => dispatch({ type: 'SUCCESS'}))
        .catch(() => dispatch({ type: 'FAIL'}))
    }
  }
}

React-Redux

By Soh Paul

React-Redux

  • 311