redux-thunk가 없는 경우의 예제 코드
<button
onClick={async () => {
const response = await fetch('https://api.countapi.xyz/visits');
const data = await response.json();
dispatch(set(data.value));
}}
>
async button without thunk
</button>
redux-thunk를 사용한 예제 코드
<button
onClick={() => {
dispatch(asyncUpFetch());
}}
>
async button with thunk
</button>
기존: 비동기 작업의 결과 데이터를 redux store에 dispatch함
추가 후: 비동기 작업을 reducer에 포함시켜 동작할 수 있게 해 유지보수에 용이
createAsyncThunk()createAsyncThunk는 비동기 작업을 처리하는 액션을 만들어준다.
액션 타입과 액션이 생성될 때 작업할 비동기 함수를 parameter로 받음.
const asyncUpFetch = createAsyncThunk('counterSlice/asyncUpFetch', async () => {
const response = await fetch('https://api.countapi.xyz/visits');
const data = await response.json();
return data.value;
});
createAsyncThunk()의 반환 객체에 자동 생성되는 프로퍼티들)
비동기 작업은 extraReducers 사용
-> redux-tool-kit에서 reducers는 action creator를 자동 생성해주지만, 비동기 작업은 자동 생성되지 않아 extraReducers에 직접 정의 필요
builder.addCase()로 비동기 작업 상태와, 각 작업 상태일 때 실행할 콜백 함수를 각각 파라미터로 전달함
const counterSlice = createSlice({
name: 'counterSlice',
initalState: {
value: 0,
status: 'Welcome',
},
reducers: {
up: (state, action) => {
state.value += action.payload;
},
},
extraReducers: builder => {
builder.addCase(asyncUpFetch.pending, (state, action) => {
state.status = 'Loading';
});
builder.addCase(asyncUpFetch.fulfilled, (state, action) => {
state.value += action.payload;
state.status = 'complete';
});
builder.addCase(asyncUpFetch.rejected, (state, action) => {
state.status = 'fail';
});
},
});
persist config에는 whitelist, blacklist라는 프로퍼티가 있음
whitelist는 persist할 리스트를 명시할 때, blacklist는 persist에 제외할 리스트를 명시할 때 사용
import { persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import { userReducer } from './userSlice';
import { cartReducer } from './cartSlice';
const userPersistConfig = {
key: 'user',
storage, // use localStorage to persist
whitelist: ['userInfo'], // Only persist the "userInfo" property
};
const cartPersistConfig = {
key: 'cart',
storage,
whitelist: ['cart'], // Only persist the "cart" property
};
const persistedUserReducer = persistReducer(userPersistConfig, userReducer);
const persistedCartReducer = persistReducer(cartPersistConfig, cartReducer);
import { combineReducers } from '@reduxjs/toolkit';
const persistedUserReducer = persistReducer(userPersistConfig, userReducer);
const persistedCartReducer = persistReducer(cartPersistConfig, cartReducer);
import { configureStore } from '@reduxjs/toolkit';
const store = configureStore({
reducer: rootReducer,
});
export default store;
직렬화를 이유로 순서를 되도록 지키라고 되어 있는데, 직렬화에 대한 내용도 잘 이해가 안되고, 순서에 대한 내용도 찾기 어려웠다.
여러 케이스로 테스트한 결과 persist+configure+(combine)를 함께 사용할 때 이 순서로 했을 때 config도 지켜지고, persist도 잘 동작하며 문제가 없었다.