redux의 단점! 많은 코드양
Redux 팀에서 단점을 보완하려고 만들어진 패키지 redux toolkit
Thunk, saga, immer 안써도 된다. 내장되어있다. 리덕스의 총집합
createSlice ,createAsyncThunk 두가지가 많이 사용된다.
npm install @reduxjs/toolkit
createAction
액션 creator함수는 간단하게 사용할 수있도록 해준다.
// 변경전
const ADD = 'add';
const DEL = 'delete';
// action creator
const AddTodo = (text) => {
return {
type: ADD,
text
}
}
const DelTodo = (id) => {
return {
type: DEL,
id
}
}
// 변경후
import { createAction } from '@reduxjs/toolkit'
const addTodo = createAction("ADD"); //인자값으로 넣어준 값이 type이 된다.
const delTodo = createAction("DEL");
콘솔로 addTodo를 찍어보면
{type: ADD, payload: } 이렇게 찍히는 것을 볼 수있다.
기존과는 다르게 action으로 부터 파라미터로 데이터를 받는다면 payload로 받게된다. (컨벤션)
reducer에서도 액션타입을 addTodo.type으로 사용할 수있다.
// 변경전
const reducer = (state = [], action) => {
switch(action.type) {
case ADD:
return ;
case DEL:
return ;
default:
return;
}
}
// 변경후
const reducer = (state = [], action) => {
switch(action.type) {
case addTodo.type: //createAction.type으로 써줄수있다.
return;
case delTodo.type:
return ;
default:
return;
}
}
createReducer()
// 기존코드
const reducer = (state = [], action) => {
switch(action.type) {
case AddTodo.type:
return ;
case DeleteTodo.type:
return ;
default:
return ;
}
}
switch문을 사용하지 않아도 된다.
const reducer = createReducer([], {
[addTodo]: (state, action) => ,
[delTodo]: (state, action) =>
})
중요한 점
state를 mutate해도 된다.
이전 reducer에서는 새로운객체를 반환해줬어야했다.
Redux toolkit에서는 mutate를 해도 괜찮다.
(주의할 점은 state를 수정해서 return하면 안된다. 수정은 수정만 하면 된다.)
createReducer를 사용하는경우 state변경 시 두가지 옵션
- 새로운 state를 리턴할수있고
- 기존 state를 mutate(수정) 하는 방식
(redux toolkit은 Immer.js 아래에서 작동되기 때문에 자체로 새로운 state를 만들어 사용한다.)
configureStore()
이 함수는 좋은 미들웨어와 함께 store를 생성한다.
configureStore를 사용하면 redux developer tools(히스토리, 디버깅이 편리하다.) 사용할 수 있다.
const store = configureStore({
reducer,
// preloadedState: 서버사이드 렌더링시 state를 받을때
});
커스텀 미들웨어가 있는 경우 middleware로 넘겨준다.
const firstMiddleWare = (store) => (next) => (action) => {
console.log('액션로깅', action);
next(action);
};
const store = configureStore({
reducer,
middleware: [firstMiddleWare]
});
커스텀 미들웨어 넘겨주는 경우
middleware: [firstMiddleWare] 이렇게 넣어주면 toolkit이 가지고 있던 thunk 미들웨어가 제외된다.
getDefaultMiddleware를 import 해서 새로운 객체를 만들어준다.
devTools도 환경에 맞춰 사용할 수 있다.
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit';
import reducer from './reducers';
const firstMiddleWare = (store) => (next) => (action) => {
console.log('액션로깅', action);
next(action);
};
const store = configureStore({
reducer,
middleware: [firstMiddleWare, ...getDefaultMiddleware()],
devTools: false // devtool 안쓸거면 false
devTools: process.env.NODE_ENV !== 'production',
enhencers
});
export default store;
createSlice()
createSlice는 reducer뿐만 아니라 actions도 생성해준다.
// 기존코드
const AddTodo = createAction("ADD");
const DeleteTodo = createAction("DELETE");
const reducer = createReducer([], {
[AddTodo]: (state, action) => {
state.push({ text: action.payload, id: Date.now() })
},
[DeleteTodo]: (state, action) => {
const filtered = state.filter((todo) => todo.id !== action.payload);
return filtered;
}
})
createSlice()는 reducer, actions를 export할 수있다.
const todos = createSlice({
name: 'todoReducer',
initialState: [],
reducers: { // 동기적 액션들, 내부적인 액션들
add: (state, action) => {
state.push({text: })
},
remove: (state, action) =>
},
extraReducers: { //비동기 액션들, 외부적인 액션들
}
})
// createSlice로 만든 todos.reducer로 export해서 사용
const store = configureStore({ reducer: todos.reducer });
// createSlice로 만든 todos.actions export해서 사용
const {add, remove} = todos.actions;
createAsyncThunk
툴킷패키지 에는 thunk가 내장되어있다.
// actions/user
const {createAsyncThunk} from '@reduxjs/toolkit';
// data(ex 아이디, 패스워드)넘기면 axios로 api호출하고 응답을 받는다.
// 코드에 user/logIn 액션이름
const login = createAsyncThunk('user/logIn', async(data, thunkAPI) => {
// pending, fulfilled, rejected
const result = axios('/url');
return result;
})
// user.reducer
createSlice({
name: 'post',
initialState,
reducers: {
}, //동기적 액션들, 내부적인 액션들(user에 종속되어있는)
extraReducers: {
[logIn.pending](state, action) { //이름은 user/logIn/pending
state = null
},
[logIn.fulfilled](state, action) { //user/logIn/fulfilled
state = action.payload;
},
[logIn.rejected](state, action) {
state = null
}
} // 비동기 액션들, 외부적인 액션들(user에 종속되어있지 않은), thunk로 만드는 애들
})
extraReducers builder를 사용해서 타입추론이 더 쉽게 수정하기
extraReducers: (builder) => builder
.addCase(LogIn.pending, (state, action) => {})
.addCase(LogIn.fulfilled, (state, action) => {})
.addCase(LogIn.rejected, (state, action) => {})
// addMatcher는 공통적인 코드 처리할 때
// action pending인경우는 공통적으로 isLoading = true로 변경한다.
.addMatcher((action) => {
// 조건
return action.type.includes('/pending');
}, (state, action) => {
state.isLoading = true
})
.addDefaultCase((state, action) => {
// default
})
createSelector
import { createSelector } from '@reduxjs/toolkit' //reselect
useMemo로 최적화보다 더 나은최적화
memoiztion을 해준다고 생각하면 된다.
export해서 다른 컴포넌트에서 사용하면 안된다.
다른컴포넌트에서 사용하고싶은경우 함수로 감싸서 다른컴포넌트에서 실행해서 그렇게 사용해야 한다.
const priceSelector = (state) => state.user.prices;
export const makeSumPriceSelector = () => createSelector{
priceSelector,
(prices) => prices.reduce(a, c => a + c, 0);
};
const sumPriceSelector = makeSumPriceSelector();
function App () {
}
'TECH' 카테고리의 다른 글
styled-components 기본 문법 (0) | 2023.02.22 |
---|---|
styled-components, emotion 비교 (0) | 2023.02.22 |
redux개념 정리 (0) | 2023.02.16 |
tsconfig.json 기본세팅, d.ts, JSDoc (0) | 2023.02.14 |
Typescript 기초개념 정리 (0) | 2023.02.14 |