개요
modal은 사용자의 이목을 집중시키기 위한 인터페이스 창이다.
문서 내의 상위에 배치되며 사용자의 이목을 집중시키기에 좋다.
모달의 on, off는 보통 bool타입의 state로 관리하는데, 전역 상태 관리에 사용하는 라이브러리인 redux를 사용해서 모달을 구현하면 코드도 줄고, 관리가 용이할 것 같다는 생각이 들어 구현하게 되었다.
사용 라이브러리
본 글은 Redux와 bootstrap modal을 사용한다.
설치 명령어는 다음과 같다.
npm i @reduxjs/toolkit bootstrap react-redux
구현
먼저 Redux가 관리할 state의 초기값을 선언한다.
redux.ts
const initialState = {
message : "",
isOpen : false,
}
message는 모달에 출력해 줄 메세지를 관리하고 isOpen은 모달의 on/off를 관리한다.
이제 리듀서 함수를 작성한다.
redux.ts
const modalReducer = (state = initialState, action: any) => {
switch(action.type){
case 'open_modal':
return {...state, isOpen : true};
case 'close_modal' :
return {...state, isOpen: false};
case 'set_message' :
return {...state, message: action.payload};
default:
return state;
}
}
액션은 총 3개를 선언했다.
open_modal, close_modal, set_message를 사용하여 모달을 관리할 것이다.
open_modal은 modal을 열고, close_modal은 모달을 닫는다.
set_message는 모달을 열기 전 모달에 표시할 메세지를 payload 값으로 변경한다.
이제 스토어를 생성해준다.
redux.ts
const store = configureStore({
reducer: {
modal: modalReducer,
}
})
export default store;
생성된 스토어는 프로젝트의 최상위 컴포넌트에 import 해주어야 한다.
보통은 Typescript 프로젝트일 경우 App.tsx가, Javascript 프로젝트일 경우 App.jsx가 최상위 컴포넌트일 것이다.
해당 파일로 가서 스토어를 import 해준다.
App.tsx
import React from 'react';
import './App.css';
import { Provider } from 'react-redux';
import store from './redux/redux'; //생성한 redux 파일의 경로로 지정
import AnyComponent from './AnyComponent
const App: React.FC = () => {
return (
<Provider store={store}>
<AnyComponent/>
</Provider>
)
}
export default App;
이런식으로 모든 컴포넌트를 Provider 태그로 감싸준다.
이제 모달을 작동시킬 함수들을 만들어야 한다.
우선 액션을 수행할 함수 3개를 작성한다.
modalActions.ts
export const openModal = () => ({
type: 'open_modal'
});
export const closeModal = () => ({
type: 'close_modal'
});
export const setMessage = (message : string) => ({
type: 'set_message',
payload : message
});
이제 이 액션 함수들로 실제로 값을 변경할 함수를 작성한다.
redux가 관리중인 상태값을 변경하기 위해 redux의 라이브러리 함수인 dispatch를 사용한다.
modalFunc.ts
import { openModal, closeModal as handleCloseModal, setMessage } from "./modalActions";
import store from "../redux/redux";
export const openModalWithMessage = (message: string) => {
store.dispatch(setMessage(message));
store.dispatch(openModal());
};
export const closeModal = () =>{
store.dispatch(handleCloseModal());
}
openModalWithMessage 함수로 프로젝트 어디에서든 원하는 메세지로 모달을 열 수 있도록 하였다.
closeModal 함수는 모달을 닫기 위해 사용한다.
이제 bootstrap모달을 작성한다.
MessageModal.tsx
import React from 'react';
import { useSelector } from 'react-redux';
import { Modal, Button, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import 'bootstrap/dist/css/bootstrap.css';
import { closeModal } from './modalFunc';
const MessageModal: React.FC = () => {
const handleModal: boolean = useSelector((state: any) => state.modal.isOpen);
const modalMessage: string = useSelector((state: any) => state.modal.message);
return (
<div>
<Modal isOpen={handleModal} fade={true}>
<ModalHeader>
Status
</ModalHeader>
<ModalBody>
{modalMessage}
</ModalBody>
<ModalFooter>
<Button color='primary' onClick={closeModal}>닫기</Button>
</ModalFooter>
</Modal>
</div>
);
};
export default MessageModal;
redux의 라이브러리 함수인 useSelector로 현재 redux의 state 값을 가져올 수 있다.
해당 값들로 모달을 구현한다.
모달을 구현한 후, 루트 컴포넌트에 import하는것을 잊지말자.
import React from 'react';
import './App.css';
import { Provider } from 'react-redux';
import store from './redux/redux'; //생성한 redux 파일의 경로로 지정
import AnyComponent from './AnyComponent
import MessageModal from './modal/MessageModal';
const App: React.FC = () => {
return (
<Provider store={store}>
<MessageModal/>
<AnyComponent/>
</Provider>
)
}
export default App;
이제 어디서든 openModalWithMessage 함수를 사용하면 원할때 원하는 메세지로 모달을 출력할 수 있다.
확장성
코드를 어떻게 작성하느냐에 따라 모달의 header값도 변경할 수 있다.
즉 어떻게, 어떤 메세지를 보여줄지에 따라 redux가 관리할 값을 늘리거나 줄일 수 있다.
예를 들어 항상 고정된 메세지만을 출력하는 모달이라면 message를 지운 후 isOpen만 redux가 관리해도 충분하다.
'React' 카테고리의 다른 글
[React] 컴포넌트의 생명주기(Lifecycle) (0) | 2023.02.10 |
---|---|
[React] 프로퍼티에 필수, 기본값 지정 / 자식 프로퍼티 사용 (0) | 2023.01.13 |
[React] 다양한 자료형 프로퍼티 사용하기 (0) | 2023.01.06 |
[React] 프로퍼티(props) 기본 (0) | 2023.01.04 |
[React] 리액트 시작하기 (0) | 2023.01.03 |