오늘은 `Redux Toolkit`(`rtk`)의 아주 기초적인 사용법에 대해 정리해보려고 한다.
지난번 Redux 기본 사용법에서는 initial state, action value, action creator, reducer를 직접 작성해주어야 했는데, `rtk`에서는 action value를 별도로 작성하지 않아도 된다. 큰 틀은 redux과 크게 다르지 않지만 세부적인 부분에서 차이점이 있다.
Redux Toolkit 사용 기초
기본 설정
먼저 아래 명령어를 실행해 rtk를 설치해주자.
yarn add react-redux @reduxjs/toolkit
이후 `src`폴더에 `redux`폴더를 만든 후 `config` 폴더와 `slices` 폴더를 만들자.
먼저 `config/configStore.js`를 만들어 아래와 같이 작성하자.
// src/redux/config/configStore.js
import { configureStore } from "@reduxjs/toolkit";
const store = configureStore({ });
export default store;
store는 지난번 redux 게시글에서 설명한 store와 동일한 역할을 한다. `configStore`에 parameter로 주어진 `{}`에는 reducers를 키로 갖는 reducer object를 넣어줄 것이다. (redux에서 `createStore`를 import하면 취소선이 생겼을 것이다. `createStore` 대신 `rtk`에서 `configureStore`를 사용하면 된다.)
다음으로 redux에서 했던 것처럼 `main.jsx`의 App 컴포넌트를 `<Provider>`로 감싸주자.
// src/main.jsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.jsx'
import './index.css'
import {Provider} from "react-redux"
import store from './redux/config/configStore.js'
createRoot(document.getElementById('root')).render(
<StrictMode>
<Provider store={store}>
{/* 모든 하위 컴포넌트에서는 store를 사용할 수 있음 */}
<App />
</Provider>
</StrictMode>,
)
redux에서는 modules 폴더에 reducer를 만들기 위한 코드를 작성했지만 `rtk`를 사용할 때에는 slice를 만들어 사용한다.
// src/redux/slices/counterSlice.js
import { createSlice } from "@reduxjs/toolkit";
// initial state
const initialState = {
number: 0,
};
const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
plus: (state, action) => {
return { number:state.number + action.payload }
}
minus: (state, action) => {
return { number:state.number - action.payload }
}
}
})
// 액션크리에이터는 컴포넌트에서 사용하기 위해 export 하고
export const { plus, minus } = counterSlice.actions;
// reducer 는 configStore에 등록하기 위해 export default 합니다.
export default counterSlice.reducer;
이전 redux에서 작성한 modules/counter.js와 비교하면 코드가 꽤 단순해진 것을 알 수 있다. 특히 action value를 설정하지 않아도 되는 것이 큰 차이점이다.
Reducer 연결하기
이제 config 파일에 reducer를 연결하자.
// src/redux/config/configStore.js
import { configureStore } from "@reduxjs/toolkit";
import counterSlice from "../Slices/counterSlice";
const store = configureStore({
reducer: { counter: counterSlice },
});
export default store;
이때 다른 slice에서 만들어진 reducer들이 더 있다면 아래 예시처럼 모두 추가로 작성해주면 된다.
import { configureStore } from "@reduxjs/toolkit";
import counterSlice from "../Slices/counterSlice";
import xSlice from "../Slices/xSlice";
import ySlice from "../Slices/ySlice";
const store = configureStore({
reducer: {
counter: counterSlice,
x: xSlice,
y: ySlice,
},
});
export default store;
이때 slice를 작성할 때 다른 slice의 reducer를 사용하게 되면 경고/에러가 발생하므로 구상할 때 주의해야 한다. (컴포넌트 내에서만 hook을 사용할 수 있다고 뜬다.)
이제 counter의 state와 reducer를 사용하는 방법에 대해 알아보자. Redux에서 했던 것처럼 원하는 컴포넌트에서 `useSelector`와 `useDispatch` hook을 사용하면 된다.
State 확인하기
`useSelector`를 사용해 store에 저장된 state를 조회할 수 있다.
// src/App.jsx
import './App.css'
import { useSelector } from 'react-redux'
function App() {
const counterReducer = useSelector((state) => {
return state.counter;
})
console.log('counterReducer :', counterReducer); // {number:0}
return (
<>
{/* your codes */}
</>
)
}
export default App
Action 전달하기
`useDispatch`와 reducer를 import해 action을 전달할 수 있다.
// src/App.jsx
import { useState } from 'react'
import './App.css'
import { useDispatch, useSelector } from 'react-redux'
import { minus, plus } from './redux/slices/counterSlice'
function App() {
const [count, setCount] = useState(0);
const counterReducer = useSelector((state) => {
return state.counter;
})
console.log('counterReducer :', counterReducer);
const dispatch = useDispatch();
// button의 action을 reducer에게 전달해줌
return (
<>
{counterReducer.number}
<input type='number' onChange={(e) => {
setCount(+e.target.value);
}} />
<button onClick={() => {
dispatch(minus(count))
}}>
빼기
</button>
<button onClick={() => {
dispatch(plus(count))
}}>
더하기
</button>
</>
)
}
export default App
'Frontend > Today I Learned' 카테고리의 다른 글
[React] useNavigate로 prop 전달하기 (0) | 2024.08.29 |
---|---|
[React] Hooks - useContext, memoization (0) | 2024.08.26 |
[JS] 이벤트 겹쳤을 때 막는 방법 (+ 이벤트 캡처링, 버블링) (0) | 2024.08.23 |
[JS, redux] Redux 소개 및 기본 사용법 (0) | 2024.08.19 |
[React] Hooks - useState, useEffect, useRef (0) | 2024.08.16 |