이번 프로젝트의 필수 사항 중 하나인 리덕스툴킷!
확실히 리덕스의 아키텍처를 먼저 이해하고 보니 리덕스 툴킷이 훨씬 사용하기 쉽고 편리하다는 걸 알 수 있었다.
우선 Redux, React Redux, Redux toolkit 각각의 역할에 대해 알아보자.
- Redux : 상태 관리자, 프로그램이 동작하는데 필요한 데이터를 체계적으로 관리해주는 도구
- 리덕스 자체는 리액트에 최적화되었다기 보다 자바스크립트로 된 프로젝트에 최적화된 도구라고 할 수 있다.
- 리액트에서 사용하기 쉽게 등장한것이 react redux이다.
- React Redux : 리덕스와 리액트를 연결시켜주는 도구
- 그럼에도 불구하고 리덕스는 많은 설정을 해줘야한다는 것과 코드의 양이 방대해지는 단점들이 생김
- 이러한 단점들을 보완하기 위해 나온것이 Redux toolkit
리덕스툴킷이 등장하게 된 배경
- 기존의 리덕스는 설정할 것이 많음
- 미들웨어를 사용하려면 설치, 설정할 것이 많음
- 반복되는 코드
- 불변성 유지의 어려움
리덕스 사용해보기
간단하게 카운터가 증가하는 앱을 생성한다고 해보자.
import React from "react"
function Counter(){
return (
<div>
<button>+</button> 0
</div>
)
}
1. store 생성 (리덕스의 store는 단일 스토어임)
import { createStore } from "redux"
//1. 리듀서 정의
function reducer(state, action){
return state;
}
//2. 초기값 제공
const initialState = { value:0 }
//3. 스토어 생성
const store = createStore(reducer, initialState);
2. Provider를 통해 앱에 공급
import { Provider } from "react-redux"
export default function App(){
return (
<Provider store={store}>
<Counter />
</Provider>
);
}
3. 카운터 컴포넌트 스토어에 있는 초기 value값을 가져오기
import React from "react"
import { useSelector } from "react-redux"
function Counter(){
const count = useSelector(state => state.value);
return (
<div>
<button>+</button> {count}
</div>
)
}
4. 앱의 버튼을 클릭했을 때 state(count)값을 바꾸는 dispatch 작업
import React from "react"
import { useSelector, useDispatch } from "react-redux"
function Counter(){
const count = useSelector(state => state.value);
const dispatch = useDispatch();
return (
<div>
<button
onClick={()=>{
dispatch({type:"up", step:2});
}}>+</button> {count}
</div>
)
}
5. dispatch 작업을 해준 뒤 이것을 받는 리듀서 작업
function reducer(state, action){
if(action.type === "up"){
// 이때, state를 리턴하는데
// 불변하게 코드를 다루기 위해 기존의 값을 복제 해준다.
return { ...state, value: state.value + action.step }
}
return state;
}
이렇게 해주면 버튼을 클릭했을 때 count가 2씩 증가하는 걸 확인할 수 있다.
💡 리덕스 툴킷을 사용해보기 전 스토어에 대해 이해해보자.
지금까지 리덕스를 활용한 코드는 모두 하나의 store에 모든 정보를 담고있다.
하지만 프로젝트의 규모가 커지면 하나의 스토어에 너무 방대한 양의 코드가 들어가면서 기능을 구별하기 어려울 수 있다.
리덕스 툴킷에서는 기능별로 작은 스토어인 slice를 하나의 스토어에 모아두고 리덕스 툴킷이 알아서 값을 만들어 준다.
이 관점을 잘 이해하고 알아두자!
리덕스툴킷 사용하기
1. Counter 기능을 위한 작은 스토어라고 할 수 있는 counterSlice를 만들어보자.
import { createSlice } from @reduxjs/toolkit;
// createSlice에는 필요한 객체들이 있다.
const counterSlice = createSlice(
// slice의 이름
name:"counter",
// 초기값
initialState:{ value:0 }
// 리듀서 공급(s를 꼭 붙여야함), 타입별로 함수정의
reducers:{
// action.type이 up일때 이 함수가 실행할 것이다.
// 리덕스를 사용할 때는 불변성때문에 복제({})를 했었는데 툴킷에서는 자동으로 해줌
up:(state, action) => {
state.value = state.value + action.step
}
}
});
2. 작은 스토어인 slice를 만들어 준 뒤에는 모아주기위해 configureStore를 사용해준다. → 하나의 거대한 스토어 만들어주기
import { configureStore } from "@reduxjs/toolkit";
// configureStore에는 객체를 전달해주면 됨
const store = configureStore({
// 필수적으로 들어가야하는 항목
// 리듀서에는 각각의 슬라이스의 리듀서들이 들어가면됨
reducer:{
// counterSlice에 들어있는 모든 리듀서들이 합쳐진 것
counter:counterSlice.reducer
}
});
3. 데이터가 필요한 컴포넌트에서 state를 가져오기 위해 useSelector 사용
import React from "react"
import { useSelector, useDispatch } from "react-redux"
function Counter(){
const dispatch = useDispatch();
const count = useSelector(state => {
return state.counter.value;
});
return (
<div>
<button
onClick={()=>{
dispatch({type:"counterSlice/up", step:2});
}}>+</button> {count}
</div>
)
}
4. 리덕스 툴킷의 action creator를 사용해서 코드를 더 간결하게 만들어보자.
import React from "react"
import { useSelector, useDispatch } from "react-redux"
function Counter(){
const dispatch = useDispatch();
const count = useSelector(state => {
return state.counter.value;
});
return (
<div>
<button
onClick={()=>{
dispatch(counterSlice.actions.payload(2))
}}>+</button> {count}
</div>
)
}
콘솔에 찍어보면 알겠지만 "counterSlice.actions.payload(2)" 했을 때 전달하는 값은 다 payload로 간다.
따라서 createSlice 값도 이렇게 변경됨
import { createSlice } from @reduxjs/toolkit;
const counterSlice = createSlice(
name:"counter",
initialState:{ value:0 }
reducers:{
up:(state, action) => {
state.value = state.value + action.payload
}
}
});
직접 액션을 직접 만들어주는 경우는 원래대로 하겠지만 action creator를 사용할때는 payload를 사용하도록 약속되어있다. → 툴킷의 장점 중 하나
완성 코드!
App.js
import React from "react";
import store from './store';
export default function App() {
return (
<Provider store={store}>
<div>
<Counter></Counter>
</div>
</Provider>
);
}
Counter.js
import React from "react";
import { Provider,useSelector,useDispatch } from 'react-redux';
import { up } from './counterSlice';
function Counter(){
const dispatch = useDispatch();
const count = useSelector(state=>{
return state.counter.value;
});
return <div>
<button onClick={()=>{
dispatch(up(2));
}}>+</button> {count}
</div>
}
counterSlice.js
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name:'counterSlice',
initialState:{value:0},
reducers:{
up:(state, action)=>{
state.value = state.value + action.payload;
}
}
});
export default counterSlice;
// 다른곳에서 사용하기 간결하게!
// counterSlice의 actions들 중에서 up을 내보내는 것.
export const {up} = counterSlice.actions;
store.js
import {configureStore} from '@reduxjs/toolkit';
import counterSlice from './counterSlice';
const store = configureStore({
reducer:{
counter:counterSlice.reducer
}
});
export default store;
📌
'Front-end > React' 카테고리의 다른 글
[React] react-date-range 라이브러리로 캘린더 만들기 (feat.date-fns) (0) | 2024.04.11 |
---|---|
[React] 리액트쿼리 useInfiniteQuery로 무한스크롤 구현하기 (0) | 2024.03.27 |
[React] 리액트쿼리(React Query)란? (0) | 2024.03.25 |
[React] react Swiper로 슬라이드 기능 구현하기 - 버튼 커스텀, breakpoints (0) | 2024.03.20 |
[React] 모달창 구현 - 라이브러리 없이 구현하기 vs Chakra UI 사용하기 (0) | 2024.03.12 |