[redux] 리덕스를 어떻게 쓰는지 알아보자~~!

김보나·2022년 10월 19일
0

React

목록 보기
14/15

오늘 하루종일 리덕스 공부를 했는데,
천천히 모르는 부분을 계속 돌려보면서 보니
예전에 봤을 때 감도 못잡았던 부분을 알아낼 수 있었다!
(회사에서 해서 집중 더 잘됨ㅋㅋㅋㅎㅎ)
아무튼 리덕스가 뭔지는 오전에 올렸으니 어떻게 사용하는지에 대해 포스팅 해보겠다.


리듀스

  • 최초 값(initialValue)와 setter(값을 변경하는 함수)를 만든다.
  • 리듀스는 디스패치에서 사용된다.
  • 리듀스에는 액션을 가지고 있는데 이 액션이 바로 setter이다.
  • 액션과 reduce를 모두 export해야 사용할 수 있다.
  • 리덕스만 사용하면 모든 값을 모든 리듀스에 넣어줘야하지만 리덕스 툴킷을 사용하면 그럴필요가 없다.
  • 리듀스의 액션함수는 순수함수이여야하며, 값을 직접 변경하면 안된다.
  • 그치만 리덕스 툴킷을 사용하면 이미 값을 복사해놓은 값에 접근해서 사용하는 것이기 때문에 직접 변경이 가능하다.

//리덕스 툴킷을 사용하지 않고 만드는 방법
//if문 대신 switch문을 사용해도 된다.
import { createStore } from 'redux';

const initialState = { counter: 0, showCounter: true };

const counterReducer = (state = initialState, action) => {
    if (action.type === 'increment') {
        return { counter: state.counter + 1, showCounter: state.showCounter };
    }

    //동적으로 변경 가능한 리듀서
    if (action.type === 'increase') {
        return {
            counter: state.counter + action.amount,
            showCounter: state.showCounter,
        };
    }

    if (action.type === 'decrement') {
        return { counter: state.counter - 1, showCounter: state.showCounter };
    }

    if (action.type === 'toggle') {
        return { showCounter: !state.showCounter, counter: state.counter };
    }

    return state;
};

//리액트 툴킷으로 리듀서를 만드는 방법

//createSlice를 임포트한다.
//자동으로 값이 복사되고 원본이 바뀌지 않아서 값을 얼마든지 바꿀 수 있다.
//모든 값을 작성하지 않아도 알아서 작성해준다.
import { createSlice } from '@reduxjs/toolkit';

const cartSlice = createSlice({
    name: 'cart',
    initialState: {
        items: [],
        totalQuantity: 0,
    },
    reducers: {
        addItemToCart(state, action) {
            const newItem = action.payload;
            const existingItem = state.items.find(
                item => item.id === newItem.id
            );
            state.totalQuantity++;
            if (!existingItem) {
                state.items.push({
                    id: newItem.id,
                    price: newItem.price,
                    quantity: 1,
                    totalPrice: newItem.price,
                    name: newItem.title,
                });
            } else {
                existingItem.quantity++;
                existingItem.totalPrice =
                    existingItem.totalPrice + newItem.price;
            }
        },
        removeItemFromCart(state, action) {
          //action.payload로 매개변수를 받아올 수 있다.
            const id = action.payload;
            const existingItem = state.items.find(item => item.id === id);
            state.totalQuantity--;
            if (existingItem.quantity === 1) {
                state.items = state.items.filter(item => item.id !== id);
            } else {
                existingItem.quantity--;
            }
        },
    },
});

export const cartActions = cartSlice.actions;

export default cartSlice;


스토어

  • 리듀서를 저장한다.
  • index.js에서 provider로 리덕스를 글로벌 선언할 때 사용한다.
  • 리듀서를 임포트해와서 configureStore에 모아준다. <- 이는 리액트 툴킷을 이용한 방법이다.
//store/index.js
import { configureStore } from '@reduxjs/toolkit';
import uiSlice from './ui-slice';
import cartSlice from './cart-slice';

const store = configureStore({
    reducer: { ui: uiSlice.reducer, cart: cartSlice.reducer },
});

export default store;


//index.js

import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import './index.css';
import App from './App';
import store from './store/index';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  //provider를 임포트해서 스토어를 넣어주면 된다.
    <Provider store={store}>
        <App />
    </Provider>
);

디스패치

  • 값을 바꾸는 컴포넌트에서 사용한다.
  • useDispatch 훅을 사용한다.
//장바구니에 아이템을 담는 코드
import Card from '../UI/Card';
import classes from './ProductItem.module.css';
import { useDispatch } from 'react-redux';
import { cartActions } from '../../store/cart-slice';

const ProductItem = props => {
    const { title, price, description, id } = props;
    const dispatch = useDispatch();

    const addToCartHandler = () => {
      //카트 아이템을 저장해준다.
        dispatch(
            cartActions.addItemToCart({
                id,
                title,
                price,
            })
        );
    };

    return (
        <li className={classes.item}>
            <Card>
                <header>
                    <h3>{title}</h3>
                    <div className={classes.price}>${price.toFixed(2)}</div>
                </header>
                <p>{description}</p>
                <div className={classes.actions}>
                  //디스패치를 온클릭에 할당
                    <button onClick={addToCartHandler}>Add to Cart</button>
                </div>
            </Card>
        </li>
    );
};

export default ProductItem;

useSelector

  • 리덕스에 저장되어 있는 값을 호출 할 때 사용한다.

import Cart from './components/Cart/Cart';
import Layout from './components/Layout/Layout';
import Products from './components/Shop/Products';
import { useSelector } from 'react-redux';

function App() {
  //state로 리듀서의 이름에 접근하여 저장된 값에 접근한다.
    const showCart = useSelector(state => state.ui.cartIsVisible);
    return (
        <Layout>
            {showCart && <Cart />}
            <Products />
        </Layout>
    );
}

export default App;

profile
우주최강 개발자가 될 때까지😈

0개의 댓글