우리 프로젝트가 모달을 오픈하는 형식으로 되어있어서
전역으로 모달을 관리해야 할 필요성을 느꼈다.
리덕스툴킷을 사용함.
어제오늘 반나절정도 찾아보면서 구현성공함!
store.js
import modalReducer from './modalSlice'; const store = configureStore({ reducer: { persistedReducer, modal: modalReducer, }, middleware, });
persist가 적용되어있었고 어떻게 추가를 해야할까 많이 헤맸는데,
백투베이직^^이라고 전에 써놨던 블로그 글을 참고해서 해결!
원래reducer: persistedReducer,
이렇게 되어있었다.
reducer: {// 이안에서 관리한다.}
객체로 만들어서 중괄호로 감싸주고 modal을 리듀서로 추가해 등록했다.
import도 잊지않고 해야한다!store.js : 기본적으로는 이렇게 한다.
import { configureStore } from '@reduxjs/toolkit'; import modalReducer from '../redux/modalSlice'; export const store = configureStore({ reducer: { //여기서 리듀서를 관리한다. modal: modalReducer, }, });
ModalSlice.js
import { createSlice } from "@reduxjs/toolkit"; const initialState = { modalType: "", isOpen: false, }; export const modalSlice = createSlice({ name: "modal", initialState, reducers: { openModal: (state, actions) => { const { modalType } = actions.payload; state.modalType = modalType; state.isOpen = true; // state.isOpen = !state.isOpen; toggle로 하고싶을땐 이렇게 하면 됨. }, closeModal: (state) => { state.isOpen = false; }, }, }); export const { openModal, closeModal } = modalSlice.actions; export const selectModal = (state) => state.modal; export default modalSlice.reducer;
import { useSelector } from "react-redux";
import Friend from "../pages/Friend";
import Letter from "../pages/Letter";
import Todo from "../pages/Todo";
import { selectModal } from "./modalSlice";
const modals = [
{
type: "FriendModal",
component: <Friend />,
},
{
type: "LetterModal",
component: <Letter />,
},
{
type: "TodoModal",
component: <Todo />,
},
];
function GlobalModal() {
// modal type을 string으로 받는다.
const { modalType, isOpen } = useSelector(selectModal);
if (!isOpen) return; //isOpen이 false일때 모달을 닫아줌
const renderModal = () => {
const findModal = modals.find((modal) => {
return modal.type === modalType;
});
return findModal.component;
};
return (
<div>
{renderModal()}
</div>
);
}
export default GlobalModal;
props를 넘기지 않아도 불러와서 바로 사용 가능하다...! 캬...
import { useDispatch } from 'react-redux';
import styled from 'styled-components';
import { openModal } from '../redux/modalSlice';
const Nav = styled.nav`
width: 400px;
border-radius: 10px;
background-color: aliceblue;
text-align: center;
filter: drop-shadow(3px 3px 5px rgba(0, 0, 0, 0.25));
margin-right: 16px;
ul {
display: flex;
list-style: none;
padding: 0;
justify-content: space-between;
}
li {
padding: 8px;
}
`;
const Menu = ({children}) => {
const dispatch = useDispatch();
const handleFriendModal = () => {
dispatch(
openModal({
modalType: "FriendModal",
isOpen: true,
})
)
}
const handleLetterModal = () => {
dispatch(
openModal({
modalType: "LetterModal",
isOpen: true,
})
)
}
const handleTodoModal = () => {
dispatch(
openModal({
modalType: "TodoModal",
isOpen: true,
})
)
}
return (
<Nav>
<ul>
<li onClick={handleFriendModal}>친구모달</li>
<li onClick={handleLetterModal}>편지모달</li>
<li onClick={handleTodoModal}>투두모달</li>
</ul>
</Nav>
)
}
export default Menu;
import React from 'react';
import GlobalModal from './redux/GlobalModal';
import Card from './pages/Card';
import styled from 'styled-components';
import Menu from './component/Menu';
const Box = styled.div`
width: 420px;
margin: 0 auto;
`;
const ModalWrap = styled.div`
display: flex;
`;
function App() {
return (
<div className="App">
<Box>
<Menu />
<ModalWrap>
<Card />
<GlobalModal />
</ModalWrap>
</Box>
</div>
);
}
export default App;
이제 모달 리덕스로 관리하는건 했고
애니메이션 주는것을 일단 하면 될 것 같다.
화면 왼쪽에 띄울 모달, 오른쪽에 띄울 모달이 있고
화면 전체에 띄울 모달이 또 있는데
이걸 어떻게 해야할지... 그게 또 숙제...
모달 닫기도 구현해야하고... 으 낼모래까지 해야하는데 할수있을까ㅠㅠ
(+) 왼쪽/오른쪽으로 나누어 모달을 띄우는 것은 포기하고
화면 전체에 띄울 모달은 absolute + z-index를 주어서 덮어버리는 것으로 해결했다.
화면에 띄우는 대부분의 컨텐츠가 두개인데다
왼쪽에 띄우는 컨텐츠는 고정이라서 할 수 있는 방법...
persist를 객체로 넣으면 안되는 모양. reducer에 객체형태로 때려넣으면 되는줄알았는데 그것도 아닌가봄...
store.js
const persistConfig = { key: 'root', version: 1, storage, }; const rootReducer = combineReducers({ userInfo, modal, //이부분 }); const persistedReducer = persistReducer( persistConfig, rootReducer, composeWithDevTools() ); const store = configureStore({ reducer: persistedReducer, middleware, });