Mission: redux-toolkit 개념 정리
리덕스
설치 및 기본 세팅법
1. 설치 명령어npm install react-redux @reduxjs/toolkit
yarn add react-redux @reduxjs/toolkit
- 기본 세팅하기
- configureStore로 데이터 중앙 저장소 만들기
import { configureStore } from "@reduxjs/toolkit"; const store = configureStore({ reducer: {}, });
- 어플리케이션 가장 최상위에 Provider 두기
import { Provider } from "react-redux"; root.render( // 여기에 Provider 두고 위의 store를 props로 넣어주기 <Provider store={store}> <BrowserRouter> <App /> </BrowserRouter> </Provider> );
- 리액트의 useState를 리덕스의 createSlice로 대체하는 예시 코드
// useState import React, { useState } from "react"; import { nanoid } from "nanoid"; const ProductComponent = () => { const [products, setProducts] = useState([ { id: nanoid(), name: "멋진 바지", price: 20000, options: [28, 30, 32], likes: 100, }, { id: nanoid(), name: "멋진 셔츠", price: 10000, options: ["small", "medium", "large"], likes: 200, }, { id: nanoid(), name: "멋진 신발", price: 30000, options: [230, 240, 250, 260, 270], likes: 300, }, ]); // ... };
// 리덕스로 변경 import React from "react"; import { configureStore, createSlice, nanoid } from "@reduxjs/toolkit"; import { Provider, useSelector } from "react-redux"; // createSlice로 products 리듀서 만들기 const products = createSlice({ name: "products", // 리덕스 스토어에서 상태를 조회할 때 사용할 이름 initialState: [ { id: nanoid(), name: "멋진 바지", price: 20000, options: [28, 30, 32], likes: 100, }, { id: nanoid(), name: "멋진 셔츠", price: 10000, options: ["small", "medium", "large"], likes: 200, }, { id: nanoid(), name: "멋진 신발", price: 30000, options: [230, 240, 250, 260, 270], likes: 300, }, ], }); // configureStore로 스토어 생성하고 products 리듀서 등록하기 const store = configureStore({ reducer: {[products.name]: products.reducer, // 다른 리듀서들도 추가로 등록할 수 있음 }, }); const ProductComponent = () => { // useSelector로 상태 조회하기 const products = useSelector((state) => state.products); // ... JSX 코드와 상태를 이용한 렌더링 및 기능 구현 ... }; // 앱 전체를 Provider로 감싸서 리덕스 스토어를 사용할 수 있도록 설정 const App = () => { return ( <Provider store={store}> <ProductComponent /> </Provider> ); };
- 데이터 가져와서 실제 화면에 보여주기
- 사용할 곳에서 useSelector import하기
import { useSelector } from "react-redux"
- 기존에 useState 썼던 곳을 useSelector로 대체하기
function App() { const products = useSelector((state) => state.상품들); (생략) }
- 리덕스 장점 활용하기
리덕스를 사용하여 데이터를 전역 상태로 관리하고, useSelector를 활용하여 각 파일에서 바로 데이터를 가져와서 사용하는 방법
리덕스를 활용하여 데이터를 아무 파일에서나 손쉽게 가져와서 사용할 수 있다. props를 내려주지 않아도 되므로 코드가 간결해지고 유지보수가 용이해진다.// App.js import { Route, Routes } from "react-router"; import Main from "./pages/Main"; import Products from "./pages/Products"; import Product from "./pages/Product"; import Layout from "./pages/Layout"; import { Link } from "react-router-dom"; import Login from "./pages/Login"; import Signup from "./pages/Signup"; function App() { return ( <Routes> <Route element={<Layout />}> <Route path="/" element={<Main />} /> <Route path="/products" element={<Products />} /> <Route path="/products/:id" element={<Product />} /> <Route path="/login" element={<Login />} /> <Route path="/signup" element={<Signup />} /> </Route> <Route path="*" element={ <> <div>없는 페이지입니다.</div> <Link to="/">홈으로 이동</Link> </> } /> </Routes> ); } export default App;
// Main.jsx import { useSelector } from "react-redux"; function Main() { const products = useSelector((state) => state.상품들); // (생략) }
// Products.jsx import { useSelector } from "react-redux"; function Products() { const products = useSelector((state) => state.상품들); // (생략) }
- 데이터를 변경하는 법: 데이터 전달이 필요 없을 때
- createSlice 파라미터 안에 reducers를 추가
reducers 안에 변경 함수를 만든다.import { createSlice } from "@reduxjs/toolkit"; let products = createSlice({ name: "상품들", initialState, reducers: { sortByPrice: (state) => { state.sort((a, b) => a.price - b.price); }, }, });
- 변경 함수를 export 해준다.
export const { sortByPrice } = products.actions;
- 해당 함수를 사용하고 싶은 곳에서 useDispatch를 사용한다.
변경 함수와 useDispatch를 import 한다.import { sortByPrice } from "../index"; import { useDispatch } from "react-redux";
- useDispatch를 선언하고 실행하고 싶은 곳에 dispatch(변경함수())와 같이 작성
const dispatch = useDispatch(); // 실행하고 싶은 곳에서 변경 함수를 dispatch dispatch(sortByPrice());
- 데이터를 변경하는 법: 데이터 전달이 필요 할 때
- 장바구니 데이터를 createSlice를 사용하여 만든다.
import { createSlice } from "@reduxjs/toolkit"; let cart = createSlice({ name: "장바구니상품들", initialState: [], reducers: {}, }); const store = configureStore({ reducer: { 상품들: products.reducer, 장바구니: cart.reducer, }, });
- 장바구니 추가 함수를 만든다.
let cart = createSlice({ name: "장바구니상품들", initialState: [], reducers: { addToCart: (state, action) => { state.push(action.payload); }, }, }); export const { addToCart } = cart.actions;
- addToCart 함수를 사용
<button onClick={() => { dispatch(addToCart(product)); }}> 장바구니 추가하기 </button>
- 파일 정리하기
src 폴더 안에 redux 폴더를 만들기.
config.js 파일을 생성하여 Redux store를 설정한다.// config.js import { configureStore } from "@reduxjs/toolkit"; import products from "./redux/products"; import cart from "./redux/cart"; const store = configureStore({ reducer: { 상품들: products.reducer, 장바구니: cart.reducer, }, }); export default store;
- products.js와 cart.js 파일을 만들고 각 파일에 해당하는 Redux slice를 작성
// products.js import { createSlice } from "@reduxjs/toolkit"; let products = createSlice({ name: "상품들", initialState: [ { id: "1", name: "멋진 바지", price: 20000, options: [28, 30, 32], likes: 100, }, { id: "2", name: "멋진 셔츠", price: 10000, options: ["small", "medium", "large"], likes: 200, }, { id: "3", name: "멋진 신발", price: 30000, options: [230, 240, 250, 260, 270], likes: 300, }, ], reducers: { sortByPrice: (state) => { state.sort((a, b) => a.price - b.price); }, }, }); export const { sortByPrice } = products.actions; export default products;
// cart.js import { createSlice } from "@reduxjs/toolkit"; let cart = createSlice({ name: "장바구니상품들", initialState: [], reducers: { addToCart: (state, action) => { state.push(action.payload); }, }, }); export const { addToCart } = cart.actions; export default cart;