redux 문서 리뷰(React Redux 7.1)
리덕스 버전 React Redux 7.1 (React 16.18.3 or later)(https://redux.js.org/)
- 앱의 예측 가능한 상태관리를 위한 컨테이너 라이브러리
- 액션, 리듀서, 스토어의 개념과 사용방법을 명확히 안다
- 툴킷이나 다른 유틸리티를 쓰지 않고 일반 함수 객체를 정의하여 생성할수 있다.
- toolKit api의 createSlice, createReducer 이용해서 생성할수도 있다.
- 유틸 모듈인 redux-actions 를 이용해 액션 생성 및 리듀서를 생성할수 있다.
- (toolKit api에서도 동일한 기능의 api를 제공하므로 toolkit을 사용하는것이 좋아보인다.)
기본 사용법
// Provider
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import store from './store'
import App from './App'
const rootElement = document.getElementById('root')
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
rootElement
)
// Customer
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import {
decrement,
increment,
incrementByAmount,
incrementAsync,
selectCount,
} from './counterSlice'
import styles from './Counter.module.css'
export function Counter() {
const count = useSelector(selectCount)
const dispatch = useDispatch()
return (
<div>
<div className={styles.row}>
<button
className={styles.button}
aria-label="Increment value"
=> dispatch(increment())}
>
+
</button>
<span className={styles.value}>{count}</span>
<button
className={styles.button}
aria-label="Decrement value"
=> dispatch(decrement())}
>
-
</button>
</div>
{/* omit additional rendering output here */}
</div>
)
}
toolkit API
configureStore
- toolkit의 configureStore 함수로 스토어를 간편하게 만들 수 있다.
- 기존 createStore와 다른점?
createSlice
- createSlice나 createReducer는 기본적으로 Immer 기능을 제공한다.
- 각 리듀서에 prepare메서드를 정의하여 액션의 인자를 받을수 있다.
- 액션과 리듀서를 하나의 객체로 정의 하여 사용할 수 있다.
import { createSlice } from '@reduxjs/toolkit' export const counterSlice = createSlice({ name: 'counter', initialState: { value: 0 }, reducers: { increment: state => { // Redux Toolkit allows us to write "mutating" logic in reducers. It // doesn't actually mutate the state because it uses the Immer library, // which detects changes to a "draft state" and produces a brand new // immutable state based off those changes state.value += 1 }, decrement: state => { state.value -= 1 }, incrementByAmount: (state, action) => { state.value += action.payload } } }) // Action creators are generated for each case reducer function export const { increment, decrement, incrementByAmount } = counterSlice.actions export default counterSlice.reducer
Hook
useSelect
- 함수형 컴포넌트에서 store로 부터 값을 가져올때 사용
useDispatch
- 함수형 컴포넌트에서 액션을 실행할때 사용
With Typescript
- 타입스크립트와 함께 사용할때 hook.ts를 정의해 놓고 아래처럼 사용하면 편리하다
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
import type { RootState, AppDispatch } from './store'
// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch = () => useDispatch<AppDispatch>()
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
비동기 동작을 위한 Thunk 미들웨어 사용하기
- 리덕스 앱에 비동기 로직을 넣을 필요성이 있을경우 사용을 권장.
- Redux Toolkit’s configureStore 를 사용하면 미들웨어를 추가할 필요없이 기본적으로 세팅이 되어있다.
- createAsyncThunk API를 사용하고, createSlice에 extraReducor의
pending, fulfilled, rejected를 구현하면 api 대기, 성공, 실패의 상태 구현을 손쉽게 구현할수 있다.