Redux
- 상태를 업데이트 할 때는 항상 원본 state는 수정하지 않고 새로운 state를 반환해야한다.
- 프로젝트가 더 복잡해질수록 리덕스를 올바르게 사용하기도 더 복잡해진다.
- 리덕스에서 관리해야 할 상태가 더 많아질 때 생길 수 있는 현상
- 액션 타입에서 문제가 생길 수 있다.
- 식별자는 오타가 나서는 안되지만 오타가 날 경우 리듀서가 처리하지 못하게 된다.
- 해결: 상수를 지정하여 오타를 막을 수 있다.
- 작은 프로젝트에서는 문제가 되지않지만 큰 프로젝트에 많은 개발자가 들어가는 프로젝트에서는 문제가 될 수 있다.
- 서로 다른 액션이 많을 때 식별자의 충돌이 발생할 수 있다.
- 관리하는 데이터의 양이 많을 수록 상태 객체도 점점 커지며 많은 상태를 복사해야한다. 모든 상태를 유지하려면 계속 복사해야하고 리듀서의 길이가 길어지고 유지할 수 없을 만큼 리덕스의 파일이 커진다. 이것은 Context의 단점과도 같고, 리덕스에서도 나타날 수 있지만 해결책이 있다.
- 상태의 변경 불가성에도 영향을 줄 수 있다.
Redux-toolkit
- Redux를 더 편리하고 쉽게 사용할 수 있도록 만들어준다.
- 위와 같은 리덕스의 단점을 해결하는 방안을 조금 더 쉽게 할 수 있고, 해결하지 못하는 단점도 보완할 수 있도록 해준다.
설치
- 아래의 코드를 작성하여 라이브러리를 설치한다.
- npm install @reduxjs/toolkit react-redux
- 기존에 설치한 Redux 라이브러리가 존재한다면 package.json에서 삭제해준다.
- 이미 Redux toolkit에 포함되어 있기 때문이다.
사용
reducer 설정
// store -> index.js
import { createSlice } from '@reduxjs/toolkit';
const initialState = { counter: 0, showCounter: true };
const counterSlice = createSlice({
// 식별자
name: 'counter',
initialState,
reducers:{
// 자동으로 최신 state를 받는다.
increment(state) {
// 기존의 상태를 변경하는 것 같지만 변경되지 않는다.
// 내부적으로 immer라는 다른 패키지를 사용한다.
// 이런 코드를 감지하고 자동으로 원래 있느 상태를 복제하고 기존 상태를 변경하지 않도록해준다.
// 불변성을 신경쓰지 않아도 된다.
state.counter++;
},
decrement(state) {
state.counter--;
},
// action에 붙어있는 데이터가 필요할 때 사용하는 방법.
increase(state, action) {
state.counter = state.counter + action.amount;
},
toggleCounter(state) {
state.showCounter = !state.ShowCounter;
}
}
});
// counterSlice.reducer에 접근 가능하다.
// 프로젝트 규모가 커졌을 경우 문제가 생길 수 있다.
// ㄴ 일반적인 redux에서는 combineReducers를 사용한다.
// ㄴ redux-toolkit에서는 configureStore를 사용한다.
// configureStore는 createStore처럼 store를 생성한다.
// 여러 개의 리듀서를 하나의 리듀서로 쉽게 합칠 수 있다.
// redux
const store = createStore(counterSlice.reducer);
// redux-toolkit
const store = configureStore({
// reducer가 하나 일 경우
reducer: counterSlice.reducer
// reducer가 여러개 일 경우
reducer: { counter: counterSlice.reducer }
});
Reducer 사용, state 가져오기
export const counterActions = counterSlice.actions;
// reudcer 사용하기
// payload가 없는 경우
dispatch(counterActions.increment());
// payload가 있는 경우
dispatch(counterActions.increase(10));