RTK 모달관리하기

KoEunseo·2022년 11월 28일
1

project

목록 보기
12/37
post-custom-banner

우리 프로젝트가 모달을 오픈하는 형식으로 되어있어서
전역으로 모달을 관리해야 할 필요성을 느꼈다.

리덕스툴킷을 사용함.

어제오늘 반나절정도 찾아보면서 구현성공함!

1. 이미 리덕스를 사용하고있는 상태.

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;

GlobalModal.js

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;

Home.js

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가 안되어서 모달 리듀서를 펄시스트에 포함하는것으로 코드를 수정했다.

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,
});
profile
주니어 플러터 개발자의 고군분투기
post-custom-banner

0개의 댓글