์ „์—ญ์—์„œ ๋ชจ๋‹ฌ ์ƒํƒœ๊ด€๋ฆฌํ•˜๊ธฐ (redux-toolkit)

2024. 9. 20. 01:17ยทWhat I Learn

๋‹น์‹œ ํผ์˜ UI ๋””์ž์ธ์ด ๋‹ค ๊ฐ™์€ ์ž‘์€ ๋ชจ๋‹ฌ์ด์—ˆ๊ณ , ์ „์—ญ์—์„œ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ํ”Œ๋กœ์šฐ์—ฌ์„œ redux-toolkit์„ ๊ฒฝํ—˜ํ•ด๋ณด๊ณ ์ž ๋„์ž…ํ•˜๋ ค๊ณ  ํ–ˆ์—ˆ๋‹ค. ์•„๋ž˜๊นŒ์ง€ ์ž‘์„ฑ ํ›„์— UI ๋””์ž์ธ์ด ์ „๋ฉด์ ์œผ๋กœ ๋ฐ”๋€Œ์–ด์„œ ํŽ˜์ด์ง€ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉํ–ฅ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ฒŒ ๋˜์—ˆ๋Š”๋ฐ ๋‹น์‹œ ์ž‘์„ฑํ•œ ๋‚ด์šฉ์„ ๊ธฐ๋กํ•˜๊ณ  ์ดํ›„ ์จ๋จน๊ธฐ ์œ„ํ•ด ์ €์žฅํ•œ๋‹ค~

 

์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋˜ Next.js ์ŠคํŽ™์€ v14 app router, ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ๋Š” src์ด๋‹ค.

src ๋‚ด์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํด๋”, ํŒŒ์ผ์„ ๋งŒ๋“ค๊ณ  ๊ทธ ์•ˆ์— ํ•„์š”ํ•œ slice๋ฅผ ์กฐ๊ฐ์กฐ๊ฐ ์ž‘์„ฑํ–ˆ๋‹ค.

// src/lib/slices/modalSlice.js

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

const initialState = {
  isOpen: false,
  modalType: null,
  modalProps: {},
};

const modalSlice = createSlice({
  name: "modal",
  initialState,
  reducers: {
    openModal: (state, action) => {
      state.isOpen = true;
      state.modalType = action.payload.modalType;
      state.modalProps = action.payload.modalProps || {};
    },
    closeModal: (state) => {
      state.isOpen = false;
      state.modalType = null;
      state.modalProps = {};
    },
  },
});

export const { openModal, closeModal } = modalSlice.actions;
export const selectModalState = (state) => state.modal;
export default modalSlice.reducer;

 

 

lib ํด๋”์— store.js๋ฅผ ๋งŒ๋“ค๊ณ  ๊ทธ ์•ˆ์— ๋งŒ๋“ค์–ด๋‘” ์Šฌ๋ผ์ด์Šค๋ฅผ ๋„ฃ์–ด์ค€๋‹ค.

 

// src/lib/store.js

import { configureStore } from "@reduxjs/toolkit";
import modalSlice from "./slices/modalSlice";

export const store = configureStore({
  reducer: {
   modal:modalSlice
  },
});

 

 

๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์— Provider๋กœ ๊ฐ์‹ธ๊ณ  export ํ•ด์ค€ ๋‹ค์Œ, ์ด๊ฑธ๋กœ root์˜ layout๋ฅผ ๊ฐ์‹ธ์ค˜์•ผํ•œ๋‹ค.

Provider๋ฅผ ๋ฐ”๋กœ root layout์— ์ ์šฉ์‹œํ‚ค๋ ค๊ณ ํ•˜๋ฉด client ์–ด์ฉŒ๊ณ .. ๋ Œ๋”๋ง ์—๋Ÿฌ๊ฐ€ ๋‚œ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  ์•„๋ž˜ ์ฝ”๋“œ์—์„œ ModalManager๋ผ๊ณ  ์ปดํฌ๋„ŒํŠธ๋ฅผ import ํ•ด์™”๋Š”๋ฐ, ์ด๊ฑด ๋ชจ๋‹ฌ ํƒ€์ž…์„ ์ •์˜ํ•ด์„œ ๋ชจ์•„๋‘˜ ์ปดํฌ๋„ŒํŠธ์ด๋‹ค.

์ž์„ธํ•œ๊ฑด ์ œ๋ผ๊ณ  ์ผ๋‹จ ์จ์ค€๋‹ค

 

// src/lib/Provider.js

"use client";
import { Provider } from "react-redux";
import { store } from "./store";
import ModalManager from "@/components/common/Modal";

export default function ReduxProvider({ children }) {
  return (
    <Provider store={store}>
      {children}
      <ModalManager />
    </Provider>
  );
}
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body className={inter.className}>
      /* <๋ฐฐ๊ฒฝ ์ปดํฌ๋„ŒํŠธ /> */
        <ReduxProvider>
          {children}
          <ModalManager />       
        </ReduxProvider>
        
      </body>
    </html>
  );
}

 

 

๋‹น์‹œ ์ƒ๊ฐํ•œ ๋ชจ๋‹ฌ์€  2๊ฐ€์ง€์˜€๋‹ค

- ์›ฐ์ปด ๋ชจ๋‹ฌ : ์ตœ์ดˆ ๋กœ๊ทธ์ธ ์‹œ์—๋งŒ ๋ณด์ผ ๊ฒƒ, ์Šฌ๋ผ์ด๋“œ ์˜ˆ์ •

- ์ด๋ฒคํŠธ ๋“ฑ๋ก ๋ชจ๋‹ฌ 

       1) ์‚ฌ๊ฑด ๋“ฑ๋ก ํผ

       2) ์˜ํ™” ๋“ฑ๋ก

              2-1) ๊ฒ€์ƒ‰์ฐฝ

              2-2) ๊ฒ€์ƒ‰์ฐฝ์—์„œ ์˜ํ™” ์„ ํƒ์‹œ ์˜ํ™” ๋ฐ์ดํ„ฐ form์— ์ž๋™ ์„ธํŒ…

 

// src/components/common/Modal.js
"use client";
import { useSelector, useDispatch } from "react-redux";
import { closeModal, openModal, selectModalState } from "@/lib/slices/modalSlice";
import { useState } from "react";

import welcomeStep1 from "....";
import welcomeStep2 from "....";
import welcomeStep3 from "....";
import welcomeStep4 from "....";

const WelcomeModal = ({ onClose }) => {
  const image = [welcomeStep1, welcomeStep2, welcomeStep3, welcomeStep4];
  const content = ["A", "B", "C", "D"];

  const [slidepage, setSlidePage] = useState(0);

  const prevSlide = () => {
    if (slidepage > 0) {
      setSlidePage(slidepage - 1);
    }
  };

  const nextSlide = () => {
    if (slidepage < content.length - 1) {
      setSlidePage(slidepage + 1);
    }
  };
  return (
    <div>
      <div>
        <div>
          {slidepage > 0 && <button onClick={prevSlide}>์ด์ „ ์Šฌ๋ผ์ด๋“œ</button>}
          {slidepage < content.length - 1 ? (
            <button onClick={nextSlide}>๋‹ค์Œ ์Šฌ๋ผ์ด๋“œ</button>
          ) : (
            <button onClick={onClose}>X</button>
          )}
        </div>
        <h2>{`Step ${slidepage + 1}`}</h2>
        <img src={image[slidepage].src} alt={`welcome modal image ${slidepage}`} />
        <p>{content[slidepage]}</p>
      </div>
    </div>
  );
};

 

 

 

์—ฌ๊ธฐ์„œ๋Š” ์›ํ•˜๋Š” ๋ชจ๋‹ฌ์˜ ๋ชจ์–‘์„ ๋งŒ๋“ค์—ˆ๋‹ค.

๋‚œ ์ด๋Ÿฐ ์‹์œผ๋กœ ๋งŒ๋“ค์—ˆ๋Š”๋ฐ ํŽ˜์ด์ง€ ๋„˜๊ธฐ๋Š” ๋ฐฉ์‹์€ ์ด์ „์— ์บ˜๋ฆฐ๋” ๋งŒ๋“ค์—ˆ๋˜ ๊ฑฐ๋ž‘ ๋น„์Šทํ•˜๊ฒŒ ํ–ˆ๋‹ค.

๋‚˜์ค‘์— ์Šฌ๋ผ์ด๋“œ์ฒ˜๋Ÿผ ๋„˜์–ด๊ฐ€๊ฒŒ ํ•˜๊ณ  ์‹ถ์€๋ฐ ์ด ๋ถ€๋ถ„์€ ํผ๋ธ”๋ฆฌ์‹ฑํ•˜๋ฉด์„œ ์ˆ˜์ •ํ•  ์˜ˆ์ •์ด๊ณ  ์ผ๋‹จ ๊ธฐ๋Šฅ๋งŒ ๋Œ์•„๊ฐ€๊ฒŒ ํ•ด๋’€๋‹ค.

 

์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ ๋ชจ๋‹ฌ๋“ค์˜ ์„ธ๋ถ€ ๋‚ด์šฉ์„ ์ž‘์„ฑํ•˜๊ณ ,  ์ด์ œ ๋ฐ‘์— ModalManager๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

const ModalManager = () => {
  const dispatch = useDispatch();
  const { isOpen, modalType, modalProps } = useSelector(selectModalState);

  if (!isOpen) return null;

  const renderModalContent = () => {
    switch (modalType) {
      case "WELCOME_MODAL":
        return <WelcomeModal {...modalProps} onClose={() => dispatch(closeModal())} />;
      {/* ์ด์™ธ์˜ case๋“ค์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋œ๋‹ค */}
      default:
        return null;
    }
  };
  return (
    <div>
      <div>{renderModalContent()}</div>
    </div>
  );
};

export default ModalManager;

 

 

renderModalContent ํ•จ์ˆ˜๋ฅผ ๋ณด๋ฉด, ์•ž์—์„œ modalSlice์—์„œ ์ž‘์„ฑํ–ˆ๋˜ openModal๋กœ ์—ด ๋•Œ ๋ชจ๋‹ฌ์„ ๊ตฌ๋ถ„ํ•ด์ค„ ๋„ค์ž„ํƒ(modalType)์„ ๋‹ฌ์•„์ค€ ๋‹ค์Œ, ์ด ๋ชจ๋‹ฌ์„ ์‚ฌ์šฉํ•  ํŽ˜์ด์ง€์— ๊ฐ€์„œ modalType์„ ํ‚ค๋กœ, ์š” ๋„ค์ž„ํƒ์„ ๊ฐ’์œผ๋กœ dispatch์— ํ˜ธ์ถœํ•ด์ฃผ๋ฉด ๋๋‹ค.

 

export default function Page() {
  const dispatch = useDispatch();
  const welcomeModalTester = () => {
   dispatch(openModal({ modalType: "WELCOME_MODAL" }));
};
 return (
   <div>
	<button onClick={welcomeModalTester}>์ด๊ฑด ์›ฐ์ปด ๋ชจ๋‹ฌ</button>
  </div>
  )
 };

 

์ €๋ ‡๊ฒŒ ์ „๋‹ฌํ•˜๋ฉด modalType์— ํ•ด๋‹นํ•˜๋Š” ๋ชจ๋‹ฌ์„ ๋„์›Œ์ฃผ๊ฒŒ ๋œ๋‹ค

์—ฌ๊ธฐ์„œ๋Š” modalProps์— ๊ฐ’์„ ์ฃผ์ง€ ์•Š์•˜์ง€๋งŒ ์ด๋ฒคํŠธ ๋ชจ๋‹ฌ์„ ๋‹ค๋ฃจ๋Š” ๋ถ€๋ถ„์—์„œ ์‚ฌ์šฉํ•  ์˜ˆ์ •์ด๋‹ค.

 

์•„์ง ๋กœ๊ทธ์ธ ๊ด€๋ จํ•ด์„œ ํ•„์š”ํ•œ ๋ถ€๋ถ„์ด ๋‚˜์˜ค์ง€ ์•Š์•„์„œ ์ดํ›„์— ๋กœ๊ทธ์ธ ๋กœ์ง ์ถ”๊ฐ€ํ•  ๋•Œ ์ฒ˜์Œ์— ๋กœ๊ทธ์ธ์„ ์„ฑ๊ณตํ•˜๋ฉด localStorage์— ์ตœ์ดˆ ๋กœ๊ทธ์ธ ๊ธฐ๋ก์„ ํ™•์ธํ•ด์„œ

1) ์—†์œผ๋ฉด ์›ฐ์ปด ๋ชจ๋‹ฌ์„ ๋ณด์—ฌ์ฃผ๋ฉด์„œ ์ตœ์ดˆ ๋กœ๊ทธ์ธ ๊ธฐ๋ก์„ ๋‚จ๊ธด๋‹ค (ํ…Œ์ด๋ธ”์— true/false๋กœ ์ปฌ๋Ÿผ์„ ๋งŒ๋“ค์–ด์•ผ ํ• ๋“ฏ)

2) ์žˆ์œผ๋ฉด 1์„ ์ œ๋ผ๊ณ  ํŽ˜์ด์ง€์˜ ๋‚ด์šฉ๋งŒ ๋ณด์—ฌ์ค€๋‹ค.

(+ ๊ทธ๋ฆฌ๊ณ  ๋งํฌ ๋ณต์‚ฌํ•ด์„œ ์œ ์ €๊ฐ€ ์•„๋‹Œ ํƒ€์ธ์—๊ฒŒ ํŽ˜์ด์ง€๋ฅผ ๋ณด์—ฌ์ค„ ๋•Œ๋Š” view๋งŒ ํ—ˆ์šฉํ•ด์•ผํ•œ๋‹ค๋Š” ์„ค์ •)

'What I Learn' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

OSSCA: customize prompt & set a completionOptions in Continue  (2) 2024.10.02
OSSCA : setting the Continue at vscode & Overview  (0) 2024.09.23
์‚ฌ์šฉ์ž ์ •์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜์œผ๋กœ ๋ณ„์ด ๋ฐ˜์งโœจ๋ฐฐ๊ฒฝ ๋งŒ๋“ค๊ธฐ (tailwindCSS)  (1) 2024.09.14
Make Calendar without Calendar library (@date-fns)  (0) 2024.09.13
Separate Next.js Root Layout from 404 Page Layout  (0) 2024.09.01
'What I Learn' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
  • OSSCA: customize prompt & set a completionOptions in Continue
  • OSSCA : setting the Continue at vscode & Overview
  • ์‚ฌ์šฉ์ž ์ •์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜์œผ๋กœ ๋ณ„์ด ๋ฐ˜์งโœจ๋ฐฐ๊ฒฝ ๋งŒ๋“ค๊ธฐ (tailwindCSS)
  • Make Calendar without Calendar library (@date-fns)
nuew
nuew
๐Ÿคธ ์žฌ์ฃผ ๋„˜๋Š” ์ค‘
  • nuew
    bloggg. . .๐Ÿฆ–๐Ÿ’ฅ
    nuew
  • ์ „์ฒด
    ์˜ค๋Š˜
    ์–ด์ œ
    • ๋ถ„๋ฅ˜ ์ „์ฒด๋ณด๊ธฐ (88)
      • issue (10)
      • baekjoon (41)
      • lecture recap (11)
      • What I Learn (26)
      • retrospective (0)
      • maeil-mail (0)
  • ๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

    • ํ™ˆ
    • ํƒœ๊ทธ
    • ๋ฐฉ๋ช…๋ก
  • ๋งํฌ

  • ๊ณต์ง€์‚ฌํ•ญ

  • ์ธ๊ธฐ ๊ธ€

  • ํƒœ๊ทธ

    ํ•œ์ž…ํฌ๊ธฐ๋กœ์ž˜๋ผ๋จน๋Š”ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ
    css
    issue
    ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ
    Algorithm
    zustand
    ์ฝ”๋”ฉํ…Œ์ŠคํŠธ
    Baekjoon
    Study
    media-query
    modal
    JavaScript
    Node.js
    TypeScript
    TailwindCSS
    js
    what i learn
    ๋ฐฑ์ค€
    ํ•œ์ž…ํฌ๊ธฐ๋กœ ์ž˜๋ผ๋จน๋Š” ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ
    ์•Œ๊ณ ๋ฆฌ์ฆ˜
  • ์ตœ๊ทผ ๋Œ“๊ธ€

  • ์ตœ๊ทผ ๊ธ€

  • hELLOยท Designed By์ •์ƒ์šฐ.v4.10.3
nuew
์ „์—ญ์—์„œ ๋ชจ๋‹ฌ ์ƒํƒœ๊ด€๋ฆฌํ•˜๊ธฐ (redux-toolkit)
์ƒ๋‹จ์œผ๋กœ

ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”