β οΈ μ 리ν λ΄μ©μ μ€νλ μλͺ»λ μ λ³΄κ° μμ μ μμ΅λλ€. λκΈλ‘ μλ €μ£Όμλ©΄ κ°μ¬νκ² μ΅λλ€.
λ¨Όμ 리λμ€λ Flux μν€ν
μ²
μ ꡬνμ²΄λ‘ λν MVC μ ν리μΌμ΄μ
μμ μ’
μ’
λνλλ λ°μ΄ν° κ° μμ‘΄μ± μ΄μλ₯Ό ν΄κ²°νκΈ° μν΄ κ³ μλμλ€.
리λμ€λ₯Ό μ¬μ©νλ ꡬ쑰μμλ μ μ μνλ₯Ό μ 보 νλμ μ μ₯μ(store) μμ μλ κ°μ²΄ νΈλ¦¬μ μ μ₯νλ©°, μνλ₯Ό λ³κ²½νλ κ²μ μ΄λ€ μΌμ΄ μμ νλ κ°μ²΄μΈ μ‘μ
(action)μ λ΄λ³΄λ΄λ(dispatch) κ²μ΄ μ μΌν λ°©λ²μ΄λ€.
κ·Έλ¦¬κ³ μ 체 μ ν리μΌμ΄μ
μ μνλ₯Ό μ΄λ»κ² λ³κ²½ν μ§ λͺ
μνκ² μν΄μλ 리λμ(reducer)μ μμ±μ΄ νμνλ€.
μ΄ λͺ¨λ μ€κ³λ λ°μ΄ν°κ° λ¨λ°©ν₯μΌλ‘ νλ₯Έλ€λ μ μ νμ λ°μ΄ν°μ μΌκ΄μ±μ ν₯μμν€κ³ λ²κ·Έ λ°μ μμΈμ λ μ½κ² νμ νλ €λ μλμμ μΆλ°νμμ μ μ μλ€.
리λμ€λ₯Ό λ μ½κ² μ¬μ©νκΈ° μν΄μ! λ§λ€μ΄μ‘λ€.
리λμ€μλ μλμ κ°μ λ¬Έμ κ° μμλ€κ³ νλ€.
- 리λμ€ μ€ν μ΄ νκ²½ μ€μ μ λ무 볡μ‘νλ€.
- 리λμ€λ₯Ό μ μ©νκ² μ¬μ©νλ €λ©΄ λ§μ ν¨ν€μ§λ₯Ό μΆκ°ν΄μΌνλ€.
- 리λμ€λ 보μΌλ¬νλ μ΄νΈ, μ¦ μ΄λ€ μΌμ νκΈ° μν΄ κΌ μμ±ν΄μΌ νλ μ½λλ₯Ό λ무 λ§μ΄ μꡬνλ€.
RTKλ 리λμ€λ₯Ό μμ±νλ νμ€ λ°©μμ΄ λκΈ° μν μλλ‘ λ§λ€μ΄μ‘λ€κ³ νλ€.
import { configureStore } from '@reduxjs/toolkit'
import rootReducer from './reducers'
const store = configureStore({ reducer: rootReducer })
μμ²λΌ μ μΈνλ©΄ κΈ°λ³Έ λ―Έλ€μ¨μ΄λ‘ redux-thunk
λ₯Ό μΆκ°νκ³ κ°λ° νκ²½μμ 리λμ€ κ°λ°μ λꡬλ₯Ό νμ±νν΄μ€λ€.
const todosReducer = createReducer(state = [], (builder) => {
builder.addCase('UPDATE_VALUE', (state, action) => {
const {someId, someValue} = action.payload;
state.first.second[someId].fourth = someValue;
})
})
createReducer
μ μ½λ°± ν¨μ μΈμλ‘ μ£Όμ΄μ§λ builder κ°μ²΄λ addCase
, addMatcher
, addDefaultCase
λΌλ λ©μλλ₯Ό μ 곡νλ€.κ° λΌμΈλ§λ€ λΉλ λ©μλλ₯Ό λλμ΄ νΈμΆνκ±°λ 체μ΄λ ννλ‘ μμ±νλ©΄ λλ€.
// AFTER
import { createAction } from '@reduxjs/toolkit'
const increment = createAction('counter/increment')
const action = increment(3)
// { type: 'counter/increment', payload: 3 }
createAction
,createReducer
ν¨μκ° λ΄λΆμ μΌλ‘ μ¬μ©λλ©° createSlice
μ μ μΈλ μ¬λΌμ΄μ€ μ΄λ¦μ λ°λΌμ 리λμμ κ·Έλ¦¬κ³ κ·Έκ²μ μμνλ μ‘μ
μμ±μμ μ‘μ
νμ
μ μλμΌλ‘ μμ±νλ€.createSlice
λ₯Ό μ¬μ©νλ©΄ createAction
,createReducer
λ₯Ό μμ±ν νμκ° μλ€.import { createSlice, PayloadAction } from '@reduxjs/toolkit'
interface Item {
id: string
text: string
}
const todosSlice = createSlice({
name: 'todos',
initialState: [] as Item[],
reducers: {
addTodo: {
reducer: (state, action: PayloadAction) => {
state.push(action.payload)
},
prepare: (text: string) => {
const id = nanoid()
return { payload: { id, text } }
},
},
},
})
const { actions, reducer } = todosSlice
export const { addTodo } = actions
export default reducer
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import { userAPI } from './userAPI'
const fetchUserById = createAsyncThunk(
'users/fetchByIdStatus',
async (userId, thunkAPI) => {
const response = await userAPI.fetchById(userId)
return response.data
}
)
const usersSlice = createSlice({
name: 'users',
initialState: { entities: [], loading: 'idle' },
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchUserById.pending, (state) => {})
.addCase(fetchUserById.fulfilled, (state, action) => {
state.entities.push(action.payload)
})
.addCase(fetchUserById.rejected, (state) => {})
},
})
dispatch(fetchUserById(123))
reduxλ₯Ό λ°°μ°λ©΄μ μ΄κ²μ κ² μ€μ ν κ², λ§λ€μ΄μΌ ν νμΌλ€μ΄ λ무 λ§μλλ° Redux Toolkitμ μ μ©νλ©΄μ λ‘μ§μ΄ λ§μ΄ κ°λ¨ν΄μ§λ κ²μ λ³Ό μ μμλ€.
νν΄ νμμ rtkμ λν΄ μμΈν μ λ¦¬ν΄ λμ κΈμ μ°Έκ³ νμλλ° μμΈν μ 리ν΄μ£Όμ μ μ΄ν΄κ° μ’ μ½κ² λ κ² κ°λ€.
μ΄μ redux-toolkitμ΄λ redux-thunk μ€μ΅νλ©΄μ 곡λΆν λ΄μ©μ μ 리νλ¬ κ°κ² μ΅λλ€!!