Redux toolkit 사용하기

남예지·2023년 8월 31일
0

Redux

목록 보기
4/5
post-thumbnail

출처 : Udemy
【한글자막】 React 완벽 가이드 with Redux, Next.js, TypeScript
https://www.udemy.com/course/best-react/

리덕스 툴킷을 사용해보자.

npm install @reduxjs/toolkit

리덕스 툴킷에는 이미 리덕스가 포함되어 있기 때문에 리덕스 라이브러리를 삭제해야한다.

package.json에서 리덕스를 삭제해주고 서버를 다시 시작해준다.

Redux toolkit 리듀서 함수 설정

Redux의 기능을 단순화 한 것이기 때문에 똑같이 store폴더 index.js에서 사용한다.

리듀서 함수부터 보자.
createSlice를 import하고 호출해준다. 객체를 인자로 생성한다.
전역상태의 slice를 미리 만들어야 한다.

모든 slice는 name, initialState, reducers 3가지를 가져야 한다.

import { createSlice } from "@reduxjs/toolkit";

createSlice({
	name: 'counter',
    initialState: initialState,
    reducers: {  // 객체 혹은 맵 안에 메서드 추가
    	increment(state){
        	state.counter++;
        },
		decrement(state){
        	state.counter--;
        },
		increase(){}, // 코드 아래에 있음
    	toggleCounter(){} // 코드 아래에 있음
    }
})

원래 있던 if case문 4개를 4개의 메서드로 넣어준 것이다.

여기 모든 메서드는 자동으로 최근 값을 받는다. (state)
액션도 자동으로 메서드를 받아올것이라 if case도 필요없다.
나중에 서로 다른 리듀서를 구별해 두고 각각에 해당하는 액션을 발생시킨다.

아무튼 이 메서드 안에서 상태를 변경시킬 수 있다.
state.counter++; 이렇게... 리덕스에서는 안되는 코드였지만 리덕스 툴킷과 createSlice를 사용하면 기존 상태를 변경할 수 없기때문에 state.counter++; 쓰는게 가능하다.

어떻게 기존 상태가 변하지 않는 걸까?
리덕스 툴킷은 내부적으로 immer라는 다른 패키지를 사용하는데 이런 코드를 감지하고 자동으로 원래 있는 상태를 복제한다. 그리고 새로운 상태객체를 생성하고, 상태를 변경할 수 없게 유지한다.

increase(){}, 메서드에는 payload가 필요하다.
툴킷에서도 액션을 리슨하는 리듀서를 가질 수 있다.
payload가 필요하면 state와 action 두 개를 받으면 된다.

increase(state, action){
	state.counter: state.counter + action.amount
},

토글은 페이로드가 필요없으니 state만 받고 showCounter를 !를 붙여 설정해 주었다.

toggleCounter(state){
	state.showCounter = !state.showCounter;
}

이제 이 slice를 어떻게 액션으로 보내는지 알아보자.

Redux toolkit state에 연결하기

createSlice를 호출해서 리턴값을 사용해야된다. 이건 전역 상태의 slice이며 카운터와 작동해야 한다.
이를 store에 등록해준다.

그리고 createStore() 메서드에 슬라이스.reducer를 넣어 리듀서를 불러올 수 있다.

const counterSlice = createSlice({ // store에 등록
	name: 'counter',
    initialState: initialState,
    reducers: {
    	increment(state){
        	state.counter++;
        },
		decrement(state){
        	state.counter--;
        },
		increase(state, action){
            state.counter: state.counter + action.amount
        },
    	toggleCounter(state){
            state.showCounter = !state.showCounter;
        }
    }
})
const store = createStore(counterSlice.reducer)

createStore에는 한 개의 리듀서만 전달해야 하지만 slice가 여러개라면 우리는 configureStore() 메서드를 사용할 수 있다.

configureStore() 메서드

configureStore는 createStore처럼 store를 만든다. 다른점은 여러 개의 리듀서를 하나의 리듀서로 쉽게 합칠 수 있다.

configureStore 메서드에는 리듀서 객체를 전달

const store = configureStore({ 
	reducer: counterSlice.reducer // 전역 상태를 담당하는 주요 리듀서로서 사용 가능
    
    //만약 slice가 여러개인 큰 프로젝트 시에는 객체로 받을 수 있다. 
    //reducer : { counter: counterSlice.reducer }
})

export default store;

아무튼 지금은 slice가 한개이니 위에걸로 쓰자.

그럼 이제 어떻게 액션을 전달해야 할까.

액션 전달

createSlice() 메서드는 서로 다른 리듀서에 해당하는 고유 액션 식별자를 자동으로 생성한다.
counterSlice.actions 이건 key로 가득한 객체이다. .뒤에는 슬라이스 함수에 들어있는 리듀서 메서드 이름과 매칭해면 된다.

export const counterActions = counterSlice.actions.toggleCounter // 액션 생성자

이런 객체는 이미 액션마다 다른 고유 식별자와 함께 타입 프로퍼티를 가지고 있다.
자동으로 생성되므로 액션 식별자에 대해 신경 쓸 필요 없다.

export까지 해주고 액션이 필요한 컴포넌트로 가면 된다.

전에 포스팅에 이어 Counter.js파일에 적용해보자.

액션 연결

Counter.js파일에 counterActions를 연결해보자.

import { counterActions } from "../store/index"

const Counter = () => {
	const dispatch = useDispatch();
    
    const incrementHandler = () => {
    	dispatch(counterActions.increment());
    }
    
}

이렇게 dispatch 안에서 counterActions를 연결하면 된다.

그러면 페이로드가 필요한 increase는 어떻게 할까?
똑같이 counterActions를 사용하고 액션 생성자 메서드 안에 객체든 숫자든 전달만 해주면 된다.

Counter.js
...
	const increase = () => {
    	dispatch(counterActions.increase(10));
    }
...

store/index.js
...
	increase(state, action) {
    	state.counter = state.counter + action.payload;
    }
...

위 코드는 리덕스 툴킷에서
{ type: SOME_UNIQUE_IDENTIFIER, payload: 10 }
이렇게 바뀌는 것이다.

payload는 리덕스 툴킷이 기본값으로 사용하는 필드명이므로, 바꿀 수 없다. 즉 store 폴더에 index.js에서도 action.amount가 아닌 action.payload로 접근해야 한다.

간결하고 유지보수가 좋아졌다. (고 한다..)

profile
총총

0개의 댓글