Skip to content

light9639/Redux-Toolkit-Middleware

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

8 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“ Redux-Toolkit-Middleware ν…œν”Œλ › νŽ˜μ΄μ§€μž…λ‹ˆλ‹€.

:octocat: https://light9639.github.io/Redux-Toolkit-Middleware/

light9639 github io_Redux-Toolkit-Middleware_

✨ Redux-Toolkit-Middleware ν…œν”Œλ › νŽ˜μ΄μ§€μž…λ‹ˆλ‹€. ✨

πŸŽ‰ React 생성

  • React 생성
npm create-react-app my-app
# or
yarn create react-app my-app
  • viteλ₯Ό μ΄μš©ν•˜μ—¬ ν”„λ‘œμ νŠΈλ₯Ό μƒμ„±ν•˜λ €λ©΄
npm create vite@latest
# or
yarn create vite
  • ν„°λ―Έλ„μ—μ„œ μ‹€ν–‰ ν›„ ν”„λ‘œμ νŠΈ 이름 λ§Œλ“  ν›„ React 선택, Typescirpt μ„ νƒν•˜λ©΄ 생성 μ™„λ£Œ.

🚀 Redux-Toolkit μ„€μΉ˜

  • Redux-Toolkit μ„€μΉ˜ λͺ…λ Ήμ–΄
npm install redux react-redux @reduxjs/toolkit
# or
yarn add redux react-redux @reduxjs/toolkit

βœ’οΈ main.tsx, App.tsx, middleware.ts, slice.ts, index.ts μˆ˜μ • λ°μž‘μ„±

⚑ main.tsx

  • react-reduxμ—μ„œ Provider ν•¨μˆ˜ κ°€μ Έμ˜¨ ν›„ store.ts νŒŒμΌμ„ import ν•œ ν›„ <Provider store={store}></Provider>으둜 <App />을 λ‘˜λŸ¬μ‹Έλ©΄ Redux-Toolkit μ‚¬μš©μ€€λΉ„ μ™„λ£Œ.
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import { Provider } from 'react-redux'
import store from './store/index'
import './index.css'

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
)

⚑ App.tsx

  • slice.tsμ—μ„œ κ°€μ Έμ˜¨ ν•¨μˆ˜λ“€μ„ μ‚¬μš©ν•˜μ—¬ state 값을 λ³€κ²½μ‹œν‚¨λ‹€.
  • index.tsμ—μ„œ νƒ€μž…μ΄ μ„ μ–Έλœ useSelector, useDispatch을 가져와 μ‚¬μš©ν•œλ‹€.
  • input 속 값을 entered에 ν• λ‹Ήν•˜μ—¬ input μ†μ˜ 숫자만큼 값을 μ¦κ°€μ‹œν‚¨λ‹€.
import { useState } from "react";
import ReactLogo from './assets/react.svg'
import { increment, decrement, incrementByAmount } from "./store/slice";
import { useSelector, useDispatch } from "./store/index";
import './App.css';

export default function App(): JSX.Element {
  const count = useSelector((state) => state.counter.value);
  const dispatch = useDispatch();

  const [entered, setEntered] = useState("");

  return (
    <div className="App">
      <div>
        <a href="https://ko.redux.js.org/introduction/getting-started/" target="_blank">
          <img src="https://camo.githubusercontent.com/7b7f04b16cc2d2d4a32985710e4d640985337a32bbb1e60cdacede2c8a4ae57b/68747470733a2f2f63646e2e776f726c64766563746f726c6f676f2e636f6d2f6c6f676f732f72656475782e737667" className="logo" alt="Redux logo" />
        </a>
      </div>
      <h1>Redux Toolkit Middleware</h1>

      <h2>Count: {count}</h2>
      <div>
        <button onClick={() => dispatch(increment())}>Increment +1</button>
        <button onClick={() => dispatch(decrement())}>Decrement -1</button>
      </div>
      <div>
        <label>
          Increment By Amount :
          <input
            type="number"
            step={1}
            value={entered}
            onChange={(e) => setEntered(e.target.value)}
            className="Input"
          />
        </label>
        <button
          onClick={() => dispatch(incrementByAmount(parseInt(entered, 10)))}
        >
          Go
        </button>
      </div>
      <div className="card">
        <p>
          Edit <code>src/App.tsx</code> and save to test HMR
        </p>
        <p className="read-the-docs">
          Click on the Redux logos to learn more
        </p>
      </div>
    </div>
  )
}

⚑ middleware.ts

  • λ¦¬λ•μŠ€ 미듀웨어λ₯Ό λ§Œλ“€μ–΄μ„œ λ‘œμ»¬μŠ€ν† λ¦¬μ§€ 값을 μ²΄ν¬ν•˜μ—¬ 값이 μžˆλ‹€λ©΄ κ°€μ Έμ˜€κ³ , μ—†λ‹€λ©΄ μƒˆλ‘œμš΄ 값을 λΆ€μ—¬ν•œλ‹€.
import { createListenerMiddleware, isAnyOf } from "@reduxjs/toolkit";
import { decrement, increment, incrementByAmount } from "./slice";
import type { RootState } from "./index";

export const listenerMiddleware = createListenerMiddleware();
listenerMiddleware.startListening({
  matcher: isAnyOf(increment, decrement, incrementByAmount),
  effect: (action, listenerApi) =>
    localStorage.setItem(
      "count",
      JSON.stringify((listenerApi.getState() as RootState).counter)
    )
});

⚑ slice.tsx

  • μ΄ˆκΈ°κ°’μ„ μ„ΈνŒ…ν•˜κ³  νƒ€μž…μ„ μ§€μ •ν•΄μ€€λ‹€.
  • reducers에 state λ³€κ²½ ν•¨μˆ˜λ₯Ό μž‘μ„±ν•œ λ‹€μŒ counterSlice.actionsλ₯Ό 톡해 λ‚΄λ³΄λ‚΄μ„œ μ‚¬μš©ν•  수 μžˆκ²Œλ” ν•œλ‹€.
import { createSlice, PayloadAction } from "@reduxjs/toolkit";

// μ΄ˆκΈ°κ°’ νƒ€μž… λ§Œλ“€κΈ°
interface CounterState {
  value: number;
}

// μ΄ˆκΈ°κ°’ μ„ΈνŒ…
const initialState: CounterState = { value: 0 };

const counterSlice = createSlice({
  name: "counter",
  initialState,
  reducers: {
    increment(state) {
      state.value++;
    },
    decrement(state) {
      state.value--;
    },
    incrementByAmount(state, action: PayloadAction<number>) {
      state.value += action.payload;
    }
  }
});

// ν•¨μˆ˜ 내보내기
export const { increment, decrement, incrementByAmount } = counterSlice.actions;

// reducer 내보내기
export default counterSlice.reducer;

⚑ index.tsx

  • counterState λ³€μˆ˜λŠ” λ‘œμ»¬μŠ€ν† λ¦¬μ§€μ—μ„œ κ°€μ Έμ˜€λŠ” 역할을 ν•œλ‹€.
  • configureStoreλ₯Ό μ΄μš©ν•˜μ—¬ μŠ€ν† μ–΄λ₯Ό μƒμ„±ν•œλ‹€.
  • RootState, AppDispatchλΌλŠ” νƒ€μž… 값을 κ°€μ Έμ˜΄μœΌλ‘œμ¨ νƒ€μž…μ„ μ§€μ •ν•œλ‹€.
  • useDispatch, useSelector에 νƒ€μž… μΆ”κ°€ν•˜μ—¬ νƒ€μž… μ„€μ •ν•œλ‹€.
import { AnyAction, configureStore } from "@reduxjs/toolkit";
import {
  TypedUseSelectorHook,
  useDispatch as _useDispatch,
  useSelector as _useSelector
} from "react-redux";
import { listenerMiddleware } from "./middleware";
import slice from "./slice";

// λ‘œμ»¬μŠ€ν† λ¦¬μ§€μ—μ„œ κ°€μ Έμ˜€κΈ°
const counterState = JSON.parse(localStorage.getItem("count") || "null");

// μŠ€ν† μ–΄ 생성
const store = configureStore({
  preloadedState: {
    counter: counterState === null ? { value: 0 } : counterState
  },
  reducer: {
    counter: slice
  },
  middleware: (getDefaultMiddleware) => [
    ...getDefaultMiddleware(),
    listenerMiddleware.middleware
  ]
});

// νƒ€μž… κ°€μ Έμ˜€κΈ°
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

export type Action = AnyAction;

// useDispatch, useSelector에 νƒ€μž… μΆ”κ°€ν•˜μ—¬ νƒ€μž… μ„€μ •
export const useDispatch: () => AppDispatch = _useDispatch;
export const useSelector: TypedUseSelectorHook<RootState> = _useSelector;

// μŠ€ν† μ–΄ 내보내기
export default store;

πŸ“Ž 좜처

About

πŸ“ Redux-Toolkit-Middleware ν…œν”Œλ › νŽ˜μ΄μ§€μž…λ‹ˆλ‹€.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published