ํ”„๋กœ์ ํŠธ/TRIP SHARE

[React, React-Native] Context API๋กœ ์ „์—ญ์ ์œผ๋กœ ๋ชจ๋‹ฌ ๊ด€๋ฆฌํ•˜๊ธฐ

๊ฐ€์šค์ด 2024. 8. 4. 01:51

Intro


ํ”„๋กœ์ ํŠธ ๋กœ์ง์—์„œ ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ฒŒ์‹œ๊ธ€์—์„œ ์ž‘์„ฑ์ž ํ”„๋กœํ•„์„ ๋ˆ„๋ฅด๊ฑฐ๋‚˜ ๋ฒˆ๊ฐœ ๋ฏธํŒ…์—์„œ 1:1 ์ฑ„ํŒ…์„ ๋ˆ„๋ฅผ ๋•Œ ์‚ฌ์šฉ์ž์˜ ํ”„๋กœํ•„์„ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋‹ฌ์ฐฝ์„ ๋ณด์—ฌ์ฃผ๋„๋ก ๊ธฐํšํ•˜์˜€๋‹ค. ํ”„๋กœํ•„ ๋ชจ๋‹ฌ์˜ ๊ฒฝ์šฐ ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€์—์„œ ๋ชจ๋‹ฌ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ๊ตฌํ˜„ํ•ด์•ผํ–ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ž‘์—…์€ ํ•œ ํŒŒ์ผ ๋‚ด์— <Modal /> ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ถ”๊ฐ€ํ•ด ๊ตฌํ˜„์„ ํ•˜๋ฉด ํ•œ ํŽ˜์ด์ง€์— ์ฝ”๋“œ๊ฐ€ ๊ธธ์–ด์ง€๊ฒŒ ๋˜๊ณ  ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์กŒ๋‹ค.

๋ชจ๋‹ฌ๋งŒ ๋”ฐ๋กœ ํŒŒ์ผ๋กœ ๋ถ„๋ฆฌํ•ด์„œ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” ์ฝ”๋“œ๊ฐ€ ๊ธธ์–ด์ง€๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋ชจ๋‹ฌ์„ ๊ตฌํ˜„ํ•  ๋•Œ๋งˆ๋‹ค ์ด์ „์— ๊ตฌํ˜„ํ–ˆ๋˜ ๋ชจ๋‹ฌ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ฐธ๊ณ ํ•˜๋ฉด์„œ ๋ชจ๋‹ฌ์˜ ์†์„ฑ์ด๋‚˜ ์Šคํƒ€์ผ์„ ๋ณต์‚ฌ/๋ถ™์—ฌ๋„ฃ์œผ๋ฉฐ ์ฝ”๋“œ๋ฅผ ์งœ๊ณ  ์žˆ๋Š” ๊ฒŒ ๋น„ํšจ์œจ์ ์œผ๋กœ ๋А๊ปด์กŒ๋‹ค.

๋‹ซ๊ธฐ๋‚˜ ๋ชจ๋‹ฌ ์™ธ์˜ ์ฐฝ์„ ๋ˆŒ๋ €์„ ๋•Œ ๋ชจ๋‹ฌ์ด ๋‹ซํžˆ๋Š” ๊ธฐ๋Šฅ๋„ ๋™์ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฑธ ๊ณตํ†ต ์ปดํฌ๋„ŒํŠธ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€ ์•Š์„๊นŒ ๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€.. ํŒ€์› ์ค‘ ํ•œ๋ถ„์ด ์ด์™€ ๋น„์Šทํ•œ ๋‚ด์šฉ์˜ ๋ธ”๋กœ๊ทธ ๊ธ€์„ ๊ณต์œ ํ•ด์ฃผ์…”์„œ ์ฐธ๊ณ ํ•ด์„œ ๋งŒ๋“ค์–ด๋ณด์•˜๋‹ค.

 

 

Context API๋กœ ๋ชจ๋‹ฌ ๊ด€๋ฆฌํ•˜๊ธฐ


๋ชจ๋‹ฌ์˜ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์ปจํ…์ŠคํŠธ์™€ ๋ชจ๋‹ฌ์„ ์—ด๊ณ  ๋‹ซ๋Š” ํ•จ์ˆ˜ ์ปจํ…์ŠคํŠธ๋ฅผ ๋งŒ๋“ค๊ณ  Provider๋กœ ์ œ๊ณตํ•œ๋‹ค.

 

  • ModalContext.jsx
import React, { createContext, useContext, useState } from 'react';

const ModalStateContext = createContext();
const ModalDispatchContext = createContext();

export const ModalProvider = ({ children }) => {
  const [modal, setModal] = useState({ type: null, props: null, onBackdropPress: null });

  const openModal = modal => {
    setModal(modal);
  };

  const closeModal = () => {
    setModal({ type: null, props: null, onBackdropPress: null });
  };

  return (
    <ModalDispatchContext.Provider value={{ openModal, closeModal }}>
      <ModalStateContext.Provider value={modal}>{children}</ModalStateContext.Provider>
    </ModalDispatchContext.Provider>
  );
};

export function useModalState() {
  return useContext(ModalStateContext);
}

export function useModalDispatch() {
  return useContext(ModalDispatchContext);
}

 

  • ModalStateContext: Modal์€ type๊ณผ props๋ฅผ ๊ฐ€์ง„ ๊ฐ์ฒด๋ฅผ ๊ฐ–๋Š”๋‹ค. (ModalContainer.jsx ์ฐธ๊ณ )
  • ModalDispatchContext: Modal์„ ์—ด๊ณ  (openModal) ๋‹ซ๋Š” (closeModal) ๊ธฐ๋Šฅ์„ ์ „์—ญ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์ปจํ…์ŠคํŠธ

์ปจํ…์ŠคํŠธ๋Š” ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด ํ•ด๋‹น ์ปจํ…์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋œ๋‹ค. ์ƒํƒœ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋„ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฆฌ๋ Œ๋”๋งํ•  ํ•„์š”๊ฐ€ ์—†์œผ๋ฏ€๋กœ ๋ถ„๋ฆฌํ•˜์˜€๋‹ค.

 

๋ชจ๋‹ฌ์€ 'react-native-modal' ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ์—ˆ๋Š”๋ฐ

https://github.com/react-native-modal/react-native-modal

 

GitHub - react-native-modal/react-native-modal: An enhanced, animated, customizable Modal for React Native.

An enhanced, animated, customizable Modal for React Native. - react-native-modal/react-native-modal

github.com

ํ•ด๋‹น Modal ์ปดํฌ๋„ŒํŠธ์˜ ์†์„ฑ๋“ค์ด ์—ฌ๋Ÿฌ ๋ชจ๋‹ฌ์— ๊ณตํ†ต์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์–ด์„œ ModalContainer ๋ผ๋Š” ๊ณตํ†ต ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค์–ด์„œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ(children)๋ฅผ ์†์„ฑ์œผ๋กœ ๋ฐ›์•„ ๊ตฌํ˜„ํ•ด ๋ณด์•˜๋‹ค.

 

  • ModalContainer.jsx
import React from 'react';
import Modal from 'react-native-modal';
import { useModalDispatch, useModalState } from '../../contexts/ModalContext';
import ProfileModal from './contents/ProfileModal';
import PublicInfoMessage from './contents/PublicInfoMessage';
import SignUpCompleteModal from './contents/SignUpCompleteModal';
import Dropdown from './contents/CitySelectModal';
import AlertModal from './contents/AlertModal';

const MODAL_CONTENTS = {
  signUpComplete: { component: SignUpCompleteModal },
  userProfile: { component: ProfileModal },
  locationDropdown: {
    component: Dropdown,
    animationInTiming: 1,
    animationOutTiming: 1,
  },
  publicInfoMessage: { component: PublicInfoMessage },
  messageAlert: {
    component: AlertModal,
    animationInTiming: 1,
    animationOutTiming: 1,
    backdropOpacity: 0,
  },
};

const ModalContainer = () => {
  const { type, props, onBackdropPress } = useModalState();
  const { closeModal } = useModalDispatch();

  if (!type) return null;

  const {
    component: Children,
    backdropOpacity = 0.3,
    animationInTiming = 300,
    animationOutTiming = 300,
    disableBackdropPress = false,
  } = MODAL_CONTENTS[type];

  return (
    <Modal
      isVisible={true}
      backdropOpacity={backdropOpacity}
      animationInTiming={animationInTiming}
      animationOutTiming={animationOutTiming}
      onBackdropPress={disableBackdropPress ? undefined : onBackdropPress || closeModal}>
      <Children {...props} />
    </Modal>
  );
};

export default ModalContainer;

 

  • MODAL_CONTENTS
    • component: ์ž์‹ ์ปดํฌ๋„ŒํŠธ (type ๋ช…์นญ)
    • ๊ทธ ์™ธ Modal ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ด€๋ จ ์†์„ฑ
  • ๋ชจ๋‹ฌ ์ปจํ…์ŠคํŠธ์—์„œ ๋ฐ›์•„์˜จ type, props, onBackdropPress ๊ฐ’๋“ค๋กœ ๋ชจ๋‹ฌ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค.

 

์ƒ์„ฑํ•œ ์ปจํ…์ŠคํŠธ์™€ ModalContainer ์ปดํฌ๋„ŒํŠธ๋Š” App์— ๋ฐฐ์น˜ํ•œ๋‹ค.

  • App.jsx
import React from 'react';
import { ModalProvider } from './src/contexts/ModalContext';
import ModalContainer from './src/components/modals/ModalContainer';

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

export default App;

 


  • ์‚ฌ์šฉ ์˜ˆ
const { openModal } = useModalDispatch();

openModal({
  type: 'userProfile',
  props: { user: { profileImage: authorImg, profileName: authorName } },
})

 

 

ํ”„๋กœ์ ํŠธ์— ๋ชจ๋‹ฌ ์ปจํ…์ŠคํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ๊ฐœ๋ฐœํ•œ ์ง€ 3์ฃผ ์ •๋„ ๋˜์—ˆ๋Š”๋ฐ ๋ชจ๋‹ฌ์„ ๊ตฌํ˜„ํ•  ๋•Œ ์ค‘๋ณต ์ฝ”๋“œ๊ฐ€ ์ค„์–ด๋“ค์—ˆ๊ณ  ๊ฐ ํŽ˜์ด์ง€์—์„œ ๋งค๋ฒˆ ๊ตฌํ˜„ํ•˜๋˜ ๋ชจ๋‹ฌ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถ„๋ฆฌํ•จ์œผ๋กœ์จ ๊ฐ€๋…์„ฑ๋„ ๋†’์•„์กŒ๋‹ค. ํŒ€์›๋“ค๋„ ๋ชจ๋‘ ๋งŒ์กฑํ•˜๋ฉฐ ์‚ฌ์šฉ์ค‘์ด๋‹ค. ๊ณตํ†ต์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์ฝ”๋“œ๋“ค์„ ์ค„์—ฌ๋‚˜๊ฐ€๋Š” ๋ฆฌํŒฉํ† ๋ง ๊ณผ์ •์„ ๊พธ์ค€ํžˆ ํ•ด์•ผ๊ฒ ๋‹ค.

 

 

 

 

 

์ฐธ๊ณ ํ•œ ์ž๋ฃŒ)


 

 

[React] ํšจ์œจ์ ์œผ๋กœ ๋ชจ๋‹ฌ ๊ด€๋ฆฌํ•˜๊ธฐ

๋ฌด๋ ค 3๊ฐœ์›” ๋งŒ์— ๋Œ์•„์™”์Šต๋‹ˆ๋‹ค... ์ด ๊ธ€์€ Portal์„ ์‚ฌ์šฉํ•œ ๋ชจ๋‹ฌ์ฐฝ ๋งŒ๋“ค๊ธฐ์—์„œ ์ด์–ด์ง‘๋‹ˆ๋‹ค. ๋ชจ๋‹ฌ์„ ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ์—์„œ ๊ทธ๋•Œ๊ทธ๋•Œ ๋ Œ๋”๋ง ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋ถˆํ•„์š”ํ•œ ์ฝ”๋“œ๋ฅผ ๋Š˜๋ฆฌ๋ฉฐ, ๊ฐ๊ฐ์˜ ์ปดํฌ๋„ŒํŠธ์—

leego.tistory.com