[React]Context를 이용한 Modal

전유덕·2024년 2월 28일
0
post-thumbnail

개요

React개발시 전역상태관리를 위한 도구로는 Redux, Recoil, Jotai 등 여러가지가 있습니다.
이번 글에서는 그런 라이브러리말고 Context를 이용해 전역상태를 관리하는 방법에 대해 알아보겠습니다. 예제로는 아주 간단한 Modal을 준비했습니다.

사용 예시

ModalContext.jsx

//ModalContext.jsx
import { createContext, useState } from "react";

//모달상태를 관리할 컨텍스트를 생성
const ModalContext = createContext();

//모달 컨텍스트를 제공하는 컴포넌트
function ModalProvider({ children }) {
  //모달이 열려있는지 여부와 모달의 내용을 상태로 관리
  const [isOpen, setIsOpen] = useState(false);
  const [modalContent, setModalContent] = useState(null);

  //모달을 열기 위한 함수
  const openModal = (content) => {
    setModalContent(content); //모달 내용을 설정
    setIsOpen(true); //모달을 열기 위해 isOpen을 true로 설정
  };

  //모달을 닫기 위한 함수
  const closeModal = () => {
    setIsOpen(false); //모달을 닫기 위해 isOpen을 false로 설정
    setModalContent(null); //모달 내용을 초기화
  };

  //ModalContext.Provider를 통해 모달 컨텍스트를 하위 컴포넌트에 제공
  return (
    <ModalContext.Provider
      value={{ isOpen, openModal, closeModal, modalContent }}
    >
      {children}
    </ModalContext.Provider>
  );
}

export { ModalContext, ModalProvider };

useModal.jsx

//useModal.jsx
import { useContext } from "react";
import { ModalContext } from "../Contexts/ModalContext";

//useModal 커스텀 훅을 정의
export const useModal = () => {
  const context = useContext(ModalContext); //모달 컨텍스트를 가져오기
  if (!context) {
    //모달 컨텍스트가 없으면 오류를 발생
    throw new Error("useModal은 모달 프로바이더 내에서 사용해야 합니다.");
  }
  return context; //모달 컨텍스트를 반환
};

Context을 사용할 때는 Custom훅을 만들어 사용하는 것이 권장되는데 그 이유는 해당 기능이 여러 컴포넌트에서 필요할 때, 이를 Custom훅으로 만들어 사용하면 코드중복을 줄이고 재사용성을 향상시킬 수 있습니다. 또한 Context를 소비하는 로직을 훅 내부에 숨길 수 있으므로 컴포넌트에서는 해당 기능을 사용하기 위해 최소한의 코드만 작성할 수 있습니다. 더불어 프로젝트의 규모에 커질경우 기능별로 Context와 Custom훅을 나누어 사용하면 유지보수성을 향상시킬 수 있습니다.

Modal.jsx

// Modal.jsx
import React from "react";
import { useModal } from "../Hooks/useModal";
import ModalCaseA from "./ModalCaseA";
import ModalCaseB from "./ModalCaseB";

function Modal() {
  const { isOpen, closeModal, modalContent } = useModal(); // 모달 관련 상태 및 함수 가져오기

  return (
    <>
      {isOpen && ( // isOpen 상태가 true일 때만 모달 렌더링
        <div>
          {modalContent === "caseA" && <ModalCaseA />}
          {modalContent === "caseB" && <ModalCaseB />}
          <button onClick={closeModal}>모달 닫기</button>
        </div>
      )}
    </>
  );
}

export default Modal;

모달을 재사용하기 위해 전체모달은 하나의 컴포넌트로 만들어 사용하고 필요에 따라 내부 컨텐츠를 교체하는 식으로 구성했습니다.

ModalCaseA.jsx

//ModalCaseA.jsx
import React from "react";

function ModalCaseA() {
  return <p>이것은 케이스 A의 내용입니다.</p>;
}

export default ModalCaseA;

ModalCaseB.jsx

import React from "react";

function ModalCaseB() {
  return <p>이것은 케이스 B의 내용입니다.</p>;
}

export default ModalCaseB;

Home.jsx

//Home.jsx
import React from "react";
import Modal from "./Modal";
import { useModal } from "../Hooks/useModal";

function Home() {
  const { openModal } = useModal();
  return (
    <div>
      <h1>모달 Example</h1>
      <button onClick={() => openModal("caseB")}>모달 열기</button>
      <Modal />
    </div>
  );
}

export default Home;

App.jsx

//App.jsx
import "./App.css";
import { ModalProvider } from "./Contexts/ModalContext";
import Home from "./Components/Home";

function App() {
  return (
    <ModalProvider>
      <Home />
    </ModalProvider>
  );
}

export default App;
profile
zi존 개발자 되고싶다ㅏㅏ(훈수 대환영!)

0개의 댓글