๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๋ฒˆ์—ญ

๋ฆฌ๋•์Šค๋กœ ๋ชจ๋‹ฌ ์ƒํƒœ ์ œ์–ดํ•˜๊ธฐ [๋ฒˆ์—ญ]

by Whiimsy 2022. 6. 10.

๐Ÿฑ‍๐Ÿ‘ค ์›๋ฌธ : https://betterprogramming.pub/react-use-redux-to-control-modal-visibility-states-8953e44b71fd

 

React: Use Redux To Control Modal Visibility States

Easily manage dialog opening and closing state

betterprogramming.pub

๋ถ€์ œ : ๋ชจ๋‹ฌ ์—ด๊ธฐ ๋ฐ ๋‹ซ๊ธฐ ์ƒํƒœ๋ฅผ ์‰ฝ๊ฒŒ ๊ด€๋ฆฌํ•˜๋Š” ๋ฒ•

 

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

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

 


๐ŸŒฏ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜

์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์‚ฌ์šฉ์ž๊ฐ€ Yes ๋˜๋Š” No๋ฅผ ํด๋ฆญํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋‹ฌ์„ ์—ฌ๋Š” ๊ฐ„๋‹จํ•œ ๋ฒ„ํŠผ์ด๋‹ค.

// main-component-v1.js 
const MainComponent = () => {
  const [ isOpen, setIsOpen ] = useState(false)
  const [ modalStatus, setModalStatus ] = useState('')

  const closeModal = () => setIsOpen(false)
  const showModal = () => setIsOpen(true)

  const onYesPressed = () => {
    setModalStatus("User pressed yes")
    closeModal()
  } 

  const onNoPressed = () => {
    setModalStatus("User pressed no")
    closeModal()
  }

  return (
    <>
      <div style={buttonContainerStyle}>
        <button style={openModalButtonStyle} onClick={showModal}>Open</button>
        { modalStatus ?? <span>{ modalStatus }</span> }
      </div>
      <YesNoModal
        isOpen={isOpen}
        onRequestClose={closeModal}
        onYesPressed={onYesPressed}
        onNoPressed={onNoPressed}
      />
    </>
  );
};

 

์ด ๋ฐฉ์‹์˜ ๊ฒฝ์šฐ MainComponent์— ์ง์ ‘ ์ •์˜๋œ isOpen ์†์„ฑ์„ ์‚ฌ์šฉํ•ด ๋ชจ๋‹ฌ ํ‘œ์‹œ ์—ฌ๋ถ€๋ฅผ ์ œ์–ดํ•˜๊ณ  ์žˆ๋‹ค. IsOpen ์†์„ฑ์ด true์ด๋ฉด ๋ชจ๋‹ฌ์ด ํ‘œ์‹œ๋˜๊ณ  ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ˆจ๊ฒจ์ง„๋‹ค.

ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ์—์„œ๋งŒ ์ด ๋ชจ๋‹ฌ์„ ์‚ฌ์šฉํ•˜๋ฉด ์ด ๋ฐฉ์‹์—๋Š” ์ „ํ˜€ ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค. ํ•˜์ง€๋งŒ, ์ด ๋ชจ๋‹ฌ์„ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์ด ๋ฐฉ์‹์€ ๋งŽ์€ ์ฝ”๋“œ ์ค‘๋ณต์„ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

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

์ด ๋ชจ๋‹ฌ์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด, ๋˜ ์ƒํƒœ ์ œ์–ด๋ฅผ ์ค‘์•™ ์ง‘์ค‘ํ™”ํ•˜๊ธฐ ์œ„ํ•ด ์–ด๋–ค ์•ก์…˜์„ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์–ด๋–จ๊นŒ? ๋ฆฌ๋•์Šค๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์ž!

 


๐ŸŒฏ ๋ฆฌ๋•์Šค๊ฐ€ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹

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

๋ฆฌ๋•์Šค ์ ์šฉ ์˜ˆ์ œ๋กœ ๋“ค์–ด๊ฐ€๊ธฐ ์ „์— ๋ฆฌ๋•์Šค์˜ ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ์š”์†Œ์ธ Action, Reducer, Store์— ๋Œ€ํ•ด ๊ฐ„๋‹จํžˆ ์•Œ์•„๋ณด์ž.

Action์€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋‚˜๋จธ์ง€ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์—๊ฒŒ ์ผ๋ถ€ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ์•Œ๋ฆฌ๊ธฐ ์œ„ํ•ด ํ˜ธ์ถœํ•˜๋Š” ์ด๋ฒคํŠธ์ด๋‹ค. ์šฐ๋ฆฌ์˜ ๊ฒฝ์šฐ YesNoModal์„ ์—ด๊ฑฐ๋‚˜ ๋‹ซ์•„์•ผ ํ•œ๋‹ค๊ณ  ๋งํ•˜๋Š” Action์„ ํ˜ธ์ถœํ•  ๊ฒƒ์ด๋‹ค.

Reducer๋Š” ์ดˆ๊ธฐ ์ƒํƒœ์™€ Action์„ ๋ฐ›์•„ ์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๊ณ , ์ƒˆ๋กœ์šด ์ƒํƒœ๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ์ˆœ์ˆ˜ํ•œ ํ•จ์ˆ˜์ด๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ, Store๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ „์ฒด ๊ธ€๋กœ๋ฒŒ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด๋‹ค. ์šฐ๋ฆฌ๋Š” Action์„ ํ˜ธ์ถœํ•ด ์ด ๊ธ€๋กœ๋ฒŒ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๊ณ  Reducer์—์„œ ์ด๋“ค์„ ์ฒ˜๋ฆฌํ•  ๊ฒƒ์ด๋‹ค.

๋ฆฌ๋•์Šค๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ๋ช‡ ์ค„์˜ ํ…์ŠคํŠธ๋กœ ์„ค๋ช…ํ•˜๊ธฐ๋Š” ์–ด๋ ต์ง€๋งŒ, ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ํ›จ์”ฌ ๋” ๋ถ„๋ช…ํ•ด์งˆ ๊ฒƒ์ด๋‹ค.

 


๐ŸŒฏ ๋ฆฌ๋•์Šค ์„ค์น˜

๋ฆฌ๋•์Šค๋ฅผ ์„ค์น˜ํ•˜๋ฉด์„œ ์‹œ์ž‘ํ•ด๋ณด์ž.

npm install redux -s

 

๋ฆฌ๋•์Šค ์ž์ฒด ์™ธ์—๋„ React-redux ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ ์„ค์น˜ํ•œ๋‹ค. React-redux๋Š” ๋ฆฌ์•กํŠธ์˜ ๊ณต์‹ ๋ฐ”์ธ๋”ฉ์œผ๋กœ ๊ธ€๋กœ๋ฒŒ ์ƒํƒœ๊ฐ€ ์–ธ์ œ ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ ์ปดํฌ๋„ŒํŠธ์—๊ฒŒ ์•Œ๋ ค์ฃผ๊ณ  ํ•ด๋‹น ๋ณ€๊ฒฝ์— ๋”ฐ๋ผ ์žฌ๋ Œ๋”๋งํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์›€์„ ์ค€๋‹ค.

npm install redux-react -s

 


๐ŸŒฏ modalsReducer.js

modalsReducer๋Š” ์ปดํฌ๋„ŒํŠธ์— ์˜ํ•ด ํŠธ๋ฆฌ๊ฑฐ ๋œ Action์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š” ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ณณ์ด๋‹ค. ์ด ์˜ˆ์‹œ์—์„  ๋ชจ๋‹ฌ์ด ํ•˜๋‚˜๋ฐ–์— ์—†์ง€๋งŒ ์ด Reducer๋ฅผ ์‚ฌ์šฉํ•ด ๋” ๋งŽ์€ ๋ชจ๋‹ฌ๋“ค์„ ๊ด€๋ฆฌํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

// modalsReducers.js
const initialState = {
    showYesNoModal: false
}

export function modalsStore(state = initialState, action) {
    const actions = {
        "ShowYesNoModal" : {
            ...state,
            showYesNoModal: true
        },
        "HideYesNoModal" : {
            ...state,
            showYesNoModal: false
        }
    }

    return actions[action.type] || state
}

 

Reducer๋Š” ์ดˆ๊ธฐ ์ƒํƒœ ๊ฐ์ฒด์™€ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•  ๋•Œ ํ˜ธ์ถœ๋˜๋Š” ํ•จ์ˆ˜๋กœ ๊ตฌ์„ฑ๋œ๋‹ค. modalsStore ํ•จ์ˆ˜๋Š” ๋งค๊ฐœ ๋ณ€์ˆ˜๋กœ ์ƒํƒœ์™€ Action์„ ๋ฐ›๋Š”๋‹ค. ์ด Action์€ ํ˜„์žฌ ์ƒํƒœ์—์„œ ์–ด๋–ค ๋ณ€ํ™”๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋Š”์ง€ ๋งํ•ด์ค€๋‹ค.

๋งŒ์•ฝ Action์˜ ํƒ€์ž…์ด ShowYesNoModal๋ผ๋ฉด, showYesNoModal ๊ฐ’์„ true๋กœ ์„ธํŒ…ํ•˜๋Š” ์ƒˆ๋กœ์šด ์ƒํƒœ(๋ชจ๋‹ฌ์ด ํ‘œ์‹œ๋œ ์ƒํƒœ)๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค. ๋ชจ๋‹ฌ์ด ํ•œ ๋ฒˆ ์—ด๋ฆฌ๋ฉด, showYesNoModal์˜ ๊ฐ’์ด false์ธ ์ƒˆ๋กœ์šด ์ƒํƒœ๋ฅผ ๋ฆฌํ„ดํ•˜๋ฉฐ HideYesNoModal ํƒ€์ž…์„ ๊ฐ€์ง„ Action์„ ๋””์ŠคํŒจ์น˜(dispatch)ํ•ด ๋ชจ๋‹ฌ์„ ๋‹ซ์„ ์ˆ˜ ์žˆ๋‹ค.

์ด Reducer๋ฅผ ์šฐ๋ฆฌ์˜ ์ปดํฌ๋„ŒํŠธ์— ์—ฐ๊ฒฐ์‹œํ‚ค๊ธฐ ์œ„ํ•ด, index.js ํŒŒ์ผ์„ ์ˆ˜์ •ํ•ด์ค€๋‹ค.

// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import { modalsStore } from './store/modals.store';
import { combineReducers } from 'redux';
import { createStore } from 'redux';

var rootReducer = combineReducers({ modalsStore })
const store = createStore(rootReducer);

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

 

๊ธฐ๋ณธ์ ์œผ๋กœ, ์šฐ๋ฆฌ๋Š” ์•ฑ์„ Provider ์ปดํฌ๋„ŒํŠธ๋กœ ๊ฐ์‹ธ๋ฉด์„œ Store๋ฅผ ๋งŒ๋“ค๊ณ  ์ปดํฌ๋„ŒํŠธ์— ์—ฐ๊ฒฐํ•œ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ๋Š” Action์„ ๋””์ŠคํŒจ์น˜ํ•  ์ˆ˜ ์žˆ๊ณ  ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ Reducer๋“ค์„ ๊ฒฐํ•ฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ์ด ์˜ˆ์‹œ์—์„œ ์šฐ๋ฆฐ modalReducer๋งŒ ๋‹ค๋ฃจ์ง€๋งŒ, notificationReducer, alertReducer ๋“ฑ ๋‹ค์–‘ํ•œ Reducer๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

MainComponent๋ฅผ ์—ฐ๊ฒฐํ•ด YesNoModal์„ ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•ด Action์„ ๋””์ŠคํŒจ์น˜ํ•ด๋ณด์ž.

// MainComponentRedux.js
import YesNoModal from './YesNoModal'
import React, { useState } from 'react';
import { connect } from 'react-redux'
import { openModalButtonStyle, buttonContainerStyle } from './MainComponent.styles'

const MainComponent = ({ showYesNoModal }) => {
  const [ modalStatus, setModalStatus ] = useState('')

  const onYesPressed = () => {
    setModalStatus("User pressed yes")
  } 

  const onNoPressed = () => {
    setModalStatus("User pressed no")  
  }

  return (
    <>
      <div style={buttonContainerStyle}>
        <button style={openModalButtonStyle} onClick={showYesNoModal}>Open</button>
        { modalStatus ?? <span>{ modalStatus }</span> }
      </div>
      <YesNoModal
        id="modal-id"
        onYesPressed={onYesPressed}
        onNoPressed={onNoPressed}
      />
    </>
  );
};

const mapDispatchToProps = (dispatch) => ({
  showYesNoModal: () => dispatch({ type: "ShowYesNoModal" })
})

export default connect(null, mapDispatchToProps)(MainComponent);

 

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด MainComponent์—์„œ ๋ชจ๋‹ฌ ์˜คํ”ˆ ์ƒํƒœ๊ฐ€ ๋” ์ด์ƒ ํ•„์š” ์—†๋‹ค. MainComponent๊ฐ€ ๋”์ด์ƒ ๋ชจ๋‹ฌ์˜ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค. ๋Œ€์‹ , ์†์„ฑ์œผ๋กœ showYesNoModal ํ•จ์ˆ˜๋ฅผ ๋ฐ›์•˜๊ณ  ์ด ๊ฒƒ์ด ๋ชจ๋‹ฌ์ด ์—ด๋ ค์•ผ ํ•  ๋•Œ ํ˜ธ์ถœ๋  ๊ฒƒ์ด๋‹ค.

ํ•˜์ง€๋งŒ ์ด showYesNoModal์ด ์–ด๋””์„œ ์˜ฌ๊นŒ? ์ด ํ•จ์ˆ˜๋Š” ์ฝ”๋“œ์˜ ๋งˆ์ง€๋ง‰ ์ค„์—์„œ ์ปดํฌ๋„ŒํŠธ์— mapDispatchtoProps๋ฅผ ์—ฐ๊ฒฐํ•  ๋•Œ ์†์„ฑ์œผ๋กœ ์ „๋‹ฌ๋œ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ ์šฐ๋ฆฌ๋Š” ShowYesNoModal ํƒ€์ž…์˜ Action์„ ์ „์†กํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ์ด๋Š” Reducer์— ์˜ํ•ด ์บก์ฒ˜๋˜๊ณ  ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•œ๋‹ค.

์ด์ œ ์šฐ๋ฆฌ๋Š” ๋ชจ๋‹ฌ์„ ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•ด YesNoModal์—์„œ์˜ ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•ด์•ผ ํ•œ๋‹ค.

// YesNoModal.js
import React from 'react';
import Modal from 'react-modal';
import { connect } from 'react-redux'

const YesNoModal = ({ closeModal, showModal, onYesPressed, onNoPressed }) => {

  const handleYesPressed = () => {
    onYesPressed()
    closeModal()
  }

  const handleNoPressed = () => {
    onNoPressed()
    closeModal()
  }

  return (
    <Modal
      isOpen={showModal}
      onRequestClose={closeModal}
      style={customStyles}
  >
    <div>Are you sure?</div>

    <div>
      <button style={buttonStyle} onClick={handleYesPressed}>Yes</button>
      <button style={buttonStyle} onClick={handleNoPressed}>No</button>
    </div>
  </Modal>
  );
};

const mapStateToProps = (state) => {
  return {
    showModal: state.modalsStore.showYesNoModal 
  }
}

const mapDispatchToProps = (dispatch) => ({
  closeModal: () => dispatch({ type: "HideYesNoModal" })
})

export default connect(mapStateToProps, mapDispatchToProps)(YesNoModal);

 

์ƒํƒœ๋ฅผ ์†์„ฑ์— ๋งคํ•‘์‹œํ‚ฌ ๋•Œ(33๋ฒˆ์งธ ์ค„), ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ธ€๋กœ๋ฒŒ Store์˜ ๋ชจ๋“  ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ๋‹ค. mapStateToProps ํ•จ์ˆ˜๋Š” ๊ธ€๋กœ๋ฒŒ ์ƒํƒœ ๊ฐ์ฒด๋ฅผ ๋ฐ›๊ณ  ์ด๊ฒƒ์„ ๋ชจ๋‹ฌ์˜ ํ‘œ์‹œ ์—ฌ๋ถ€๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์†์„ฑ์„ ๊ฐ€์ง„ ๋˜ ๋‹ค๋ฅธ ๊ฐ์ฒด์— ๋งคํ•‘์‹œํ‚จ๋‹ค.

showModal ์†์„ฑ ์ด์™ธ์—๋„, ์ปดํฌ๋„ŒํŠธ๋Š” closeModal์ด๋ผ ๋ถˆ๋ฆฌ๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฐ›๋Š”๋‹ค. ํ•œ ๋ฒˆ ํ˜ธ์ถœ๋˜๋ฉด, ๋ชจ๋‹ฌ์˜ ํ‘œ์‹œ ์—ฌ๋ถ€ ์†์„ฑ์„ false๋กœ ์„ธํŒ…ํ•˜๋ฉฐ, Reducer์— ์˜ํ•ด ์บก์ณ๋˜๊ณ  ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” HideYesNoModal ํƒ€์ž…์„ ๊ฐ€์ง„ Action์„ ๋””์ŠคํŒจ์น˜ํ•  ๊ฒƒ์ด๋‹ค.

 

์ด ๊ฒƒ์ด ๋ฐ”๋กœ ๋ฆฌ๋•์Šค์— ์˜ํ•ด ๊ด€๋ฆฌ๋˜๋Š” ๊ธ€๋กœ๋ฒŒ ์ƒํƒœ๋“ค์„ ์‚ฌ์šฉํ•ด ๋ชจ๋‹ฌ์„ ์ œ์–ดํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. ์ด ์‹œ์ ์—์„œ, "๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด ๋” ๋งŽ์€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š”๋ฐ ์™œ ๋ฆฌ๋•์Šค๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ?"๋ผ๋Š” ์˜๋ฌธ์ด ์ƒ๊ธธ ๊ฒƒ์ด๋‹ค.

์œ„์˜ ์˜ˆ์‹œ์—์„œ ์šฐ๋ฆฌ๋Š” ๋‹จ ํ•˜๋‚˜์˜ ๋ชจ๋‹ฌ๋งŒ์„ ์‚ฌ์šฉํ–ˆ๋‹ค. ๋งŒ์•ฝ ์šฐ๋ฆฌ๊ฐ€ ๋” ๋งŽ์€ ๋‹ค๋ฅธ ๋ชจ๋‹ฌ๋“ค์„ ์‚ฌ์šฉํ•˜๋ฉด ์–ด๋–จ๊นŒ? ์ปดํฌ๋„ŒํŠธ์—์„œ ์ง์ ‘ ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ๋ชจ๋‹ฌ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•  ๊ฒƒ์ธ๊ฐ€? ์•„๋งˆ ์•„๋‹ ๊ฒƒ์ด๋‹ค!

ํ•œ ๋ฒˆ ์ฒซ ๋ฒˆ์งธ Reducer๋ฅผ ์ž‘์„ฑํ•˜๊ณ  app์— ์—ฐ๊ฒฐํ•ด ๋†“์œผ๋ฉด, ์ƒˆ๋กœ์šด Reducer๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์€ ์ƒ๋‹นํžˆ ๊ฐ„๋‹จํ•  ๊ฒƒ์ด๋‹ค. ๊ทธ๊ฒƒ๋“ค์„ index.js ํŒŒ์ผ์— ์ž„ํฌํŠธํ•˜๊ณ  Store๋ฅผ ๋งŒ๋“ค ๋•Œ ๊ฒฐํ•ฉํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.

๋‚ด ์˜ˆ์ „ ํ”„๋กœ์ ํŠธ ์ค‘ ํ•˜๋‚˜์—์„œ ์‹ค์ œ๋กœ ๊ตฌํ˜„ํ–ˆ๋˜ Reducer๋ฅผ ๊ณต์œ ํ•˜๊ณ ์ž ํ•œ๋‹ค. ์ด ๊ธ€์—์„œ ๋…ผ์˜ํ•œ ๋‚ด์šฉ๊ณผ ์ •ํ™•ํžˆ ๊ฐ™์„ ๊ฒƒ์ด๋‹ค.

// real-life-example.js
import { modalConstants } from '../constants';

const initialState = {
  showUserRegisterModal: false,
  showSchoolDetailsModal: false,
  showAdvancedQueryModal: false,
};

export function modals(state = initialState, action) {
  const actions = {
    [modalConstants.SHOW_USER_REGISTER_MODAL]: {
      ...state,
      showUserRegisterModal: true,
      message: action.message,
      redirectAfterRegister: action.redirectAfterRegister,
      actionToExecuteAfterRegister: action.actionToExecuteAfterRegister,
    },
    [modalConstants.CLOSE_USER_REGISTER_MODAL]: {
      ...state,
      showUserRegisterModal: false,
    },
    [modalConstants.SHOW_ADVANCED_QUERY_MODAL]: {
      ...state,
      showAdvancedQueryModal: true,
    },
    [modalConstants.CLOSE_ADVANCED_QUERY_MODAL]: {
      ...state,
      showAdvancedQueryModal: false,
    },
    [modalConstants.SHOW_SCHOOL_MODAL]: {
      ...state,
      showSchoolDetailsModal: true,
      school: action.school,
    },
    [modalConstants.CLOSE_SCHOOL_MODAL]: {
      ...state,
      showSchoolDetailsModal: false,
    },
    [modalConstants.SHOW_LOGIN_MODAL]: {
      ...state,
      message: action.message,
      showLoginModal: true,
    },
    [modalConstants.CLOSE_LOGIN_MODAL]: {
      ...state,
      showLoginModal: false,
    },
    [modalConstants.SHOW_SEARCHES_MODAL]: {
      ...state,
      showSearchesModal: true,
      searches: action.searches,
    },
    [modalConstants.CLOSE_SHOW_SEARCHES_MODAL]: {
      ...state,
      showSearchesModal: false,
    },
    [modalConstants.SHOW_FAVORITE_SCHOOLS_MODAL]: {
      ...state,
      showFavoriteSchoolsModal: true,
      schools: action.schools,
    },
    [modalConstants.CLOSE_FAVORITE_SCHOOLS_MODAL]: {
      ...state,
      showFavoriteSchoolsModal: false,
    },
    [modalConstants.SHOW_SCHOOLS_TO_VISIT_MODAL]: {
      ...state,
      showShoolsToVisitModal: true,
      schools: action.schools,
    },
    [modalConstants.CLOSE_SCHOOLS_TO_VISIT_MODAL]: {
      ...state,
      showShoolsToVisitModal: false,
    },
    [modalConstants.SHOW_RECOVER_PASSWORD_MODAL]: {
      ...state,
      showRecoverPasswordModal: true,
    },
    [modalConstants.CLOSE_RECOVER_PASSWORD_MODAL]: {
      ...state,
      showRecoverPasswordModal: false,
    },
  };

  return actions[action.type] || state;
}

 

์ด ์˜ˆ์ œ์˜ ์ดˆ์ ์€ ๋ชจ๋‹ฌ์„ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์ด์—ˆ์ง€๋งŒ, ์ด ์ ‘๊ทผ๋ฒ•์„ ๊ฒฝ๊ณ , ์•Œ๋ฆผ, ์ธ์ฆ ๋“ฑ๊ณผ ๊ฐ™์ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด์—์„œ ์ƒํƒœ ์ œ์–ด๋ฅผ ๊ณต์œ ํ•ด์•ผ ํ•˜๋Š” ์ž‘์—…๋“ค๋กœ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.

์˜ค๋Š˜์€ ์—ฌ๊ธฐ๊นŒ์ง€. ๊ธ€์ด ์–ด๋–ค ์‹์œผ๋กœ๋“  ๋„์›€์ด ๋˜์—ˆ๊ธฐ๋ฅผ ๋ฐ”๋ž€๋‹ค.

๋ชธ์กฐ์‹ฌํ•˜์‹œ๊ณ  ํ–‰๋ณตํ•œ ์ฝ”๋”ฉ ๋˜๊ธธ!
์†Œ์Šค ์ฝ”๋“œ๋Š” ๊นƒํ—ˆ๋ธŒ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

 

๐Ÿฑ‍๐Ÿ‘ค ์ฐธ๊ณ  : -