Redux middleware와 Async Logic 및 Data Fetching

Lucy·2023년 4월 2일
0

React

목록 보기
7/7

Redux reducer는 side effects를 포함할 수 없다.

side effects란 함수의 반환 값 외에 볼 수 있는 상태/동작의 모든 변경 사항이다.
Ex.
- 콘솔에 값 로깅
- 파일 저장
- 비동기 타이머 설정
- AJAX HTTP 요청
- 함수 외부에 존재하는 일부 상태를 수정하거나 함수에 대한 인수 변경
- 난수 또는 고유한 난수 id 생성

이러한 Side effects는 Redux Middleware에서 수행될 수 있다.

대표적으로 상태에 관해 외부 Server에 http request로 받은 데이터를 fetch하여 들고오는 경우 비동기 처리를 하여야 한다.

How?

비동기 middleware 함수를 action 객체가 아니라 dispatch로 넘겨, dispatch 전에 middleware가 먼저 실행될 수 있도록 한다.

Async Data Flow

Redux Thunk Middleware

Redux의 공식 async function middleware

Configure

npm install redux-thunk

Redux Thunk Function

dispatch와 getState를 인수로 받는 함수로, 어떤 Redux store가 사용되는지 알지 못하는 채로 비동기 로직을 미리 작성할 수 있다.

Ex.

// index.js

import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import './index.css'
import App from './App'

import './api/server'

import store from './store'
import { fetchTodos } from './features/todos/todosSlice'

store.dispatch(fetchTodos)

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
)
// store에 thunk 사용할 수 있도록 update

import { createStore, applyMiddleware } from 'redux'
import thunkMiddleware from 'redux-thunk'
import { composeWithDevTools } from 'redux-devtools-extension'
import rootReducer from './reducer'

const composedEnhancer = composeWithDevTools(applyMiddleware(thunkMiddleware))

// The store now has the ability to accept thunk functions in `dispatch`
const store = createStore(rootReducer, composedEnhancer)
export default store
// thunk function

import { client } from '../../api/client'

const initialState = []

export default function todosReducer(state = initialState, action) {
  switch (action.type) {
    // omit other reducer cases
    case 'todos/todosLoaded': {
      // Replace the existing state entirely by returning the new value
      return action.payload
    }
    default:
      return state
  }
}

// thunk function
export async function fetchTodos(dispatch, getState) {
  const response = await client.get('/fakeApi/todos')
  dispatch({ type: 'todos/todosLoaded', payload: response.todos })
}

Ref

https://redux.js.org/tutorials/fundamentals/part-6-async-logic

https://redux.js.org/tutorials/fundamentals/part-7-standard-patterns

https://redux.js.org/tutorials/fundamentals/part-8-modern-redux

profile
나아가는 OnlyOne 개발자

0개의 댓글