[Redux Toolkit] - 리덕스 툴킷 사용하기

Donggu(oo)·2023년 5월 9일

Redux

목록 보기
4/6
post-thumbnail

1. install 및 디렉토리 구조


npm install react-redux
npm install @reduxjs/toolkit

2. Redux Toolkit의 구조


1) Store

1-1. configureStore

  • configureStore 함수는 리덕스 라이브러리의 createStore 함수를 추상화한 것이다. 기존의 번거로웠던 리덕스 설정을 간편하게 할 수 있도록 해주고 설정시 디폴트로 redux-thunk와 DevTools를 제공한다.
// store.js

import { configureStore } from '@reduxjs/toolkit';
import counterSlice from '../slice/counterSlice';
import authSlice from '../slice/authSlice';

const store = configureStore({
  reducer: {
    counterSlice: counterSlice.reducer,
    authSlice: authSlice.reducer
  }
});

export default store;
// index.js

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

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Provider store={store}>
    <App />
  </Provider>
);

2) Slice

2-1. createSlice

  • createSlice 함수는 선언한 slice의 name에 따라서 actionCreator, actionType, Reducer를 자동으로 생성해준다. 따라서 별도로 createAction이나 createReducer를 사용하지 않아도 된다.
// counterSlice.js

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

const initialCounterState = { countNum: 0, isCountNum: true };

const counterSlice = createSlice({
  name: 'counter',
  initialState: initialCounterState,
  reducers: {
    increaseByOne(state) {
      state.countNum++;
    },
    decreaseByOne(state) {
      state.countNum--;
    },
    increaseByFive(state, action) {
      state.countNum = state.countNum + action.payload;
    },
    toggle(state) {
      state.isCountNum = !state.isCountNum;
    }
  }
})

export const { increaseByOne, decreaseByOne, increaseByFive, toggle } = counterSlice.actions;
export default counterSlice;
// authSlice.js

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

const initialAuthState = { isAuthenticated: false };

const authSlice = createSlice({
  name: 'authentication',
  initialState: initialAuthState,
  reducers: {
    login(state) {
      state.isAuthenticated = true;
    },
    logout(state) {
      state.isAuthenticated = false;
    }
  }
})

export const { login, logout } = authSlice.actions;
export default authSlice;

3) Counter component

// Counter.js

import { useDispatch, useSelector } from 'react-redux';
import { increaseByOne, decreaseByOne, increaseByFive, toggle } from '../redux/slice/counterSlice';

function Counter() {
  const dispatch = useDispatch();
  const counterState = useSelector((state) => state.counterSlice);

  const incrementHandler = () => {
    dispatch(increaseByOne());
  }

  const increaseHandler = () => {
    dispatch(increaseByFive(5));
  }

  const decrementHandler = () => {
    dispatch(decreaseByOne());
  }

  const toggleCounterHandler = () => {
    dispatch(toggle());
  };

  return (
    <main className={classes.counter}>
      <h1>Redux Counter</h1>
      {counterState.isCountNum ? <div className={classes.value}>{counterState.countNum}</div> : null}
      <div>
        <button onClick={incrementHandler}>+1</button>
        <button onClick={increaseHandler}>+5</button>
        <button onClick={decrementHandler}>-1</button>
      </div>
      <button onClick={toggleCounterHandler}>Toggle Counter</button>
    </main>
  );
};

export default Counter;

4) Auth component

import { useDispatch } from 'react-redux';
import { login } from '../redux/slice/authSlice';

function Auth() {
  const dispatch = useDispatch();

  const loginHandler = (e) => {
    e.preventDefault();
    dispatch(login());
  }

  return (
    <main className={classes.auth}>
      <section>
        <form onSubmit={loginHandler}>
          <div className={classes.control}>
            <label htmlFor='email'>Email</label>
            <input type='email' id='email' />
          </div>
          <div className={classes.control}>
            <label htmlFor='password'>Password</label>
            <input type='password' id='password' />
          </div>
          <button>Login</button>
        </form>
      </section>
    </main>
  );
};

export default Auth;

5) Header component

// Header.js

import { useDispatch, useSelector } from 'react-redux';
import { logout } from '../redux/slice/authSlice';

function Header() {
  const dispatch = useDispatch();
  const authState = useSelector((state) => state.authSlice.isAuthenticated);

  const logoutHandler = () => {
    dispatch(logout());
  }

  return (
    <header className={classes.header}>
      <h1>Redux Auth</h1>
      {authState ?
        <nav>
          <ul>
            <li>
              <a href='/'>My Products</a>
            </li>
            <li>
              <a href='/'>My Sales</a>
            </li>
            <li>
              <button onClick={logoutHandler}>Logout</button>
            </li>
          </ul>
        </nav>
        : null}
    </header>
  );
};

export default Header;
profile
FE Developer

0개의 댓글