RTK 모달 상태관리하기

KoEunseo·2022년 12월 2일
0

파헤쳐보자

목록 보기
17/31

1. RTK 모달 상태관리를 전역으로 하는 이유!

오무 서비스는 페이지가 바뀌지 않고 모달을 열고 닫으면서 서비스를 이용하는 형태입니다.
보통은 한 페이지에서 한개 이상의 모달을 띄우는 일이 없을 것입니다.
그러나 저처럼 여러개의 모달을 띄우는 작업이 필요할 때가 여러분에게도 올수 있지 않을까 싶습니다.
모든 모달의 상태를 각각 const [isOpen, setIsOpen] = useState(false);
로 주기에는 관리해야 할 모달이 너무 많았습니다.
같은 코드를 반복해서 치는 것에 지치기도 했고,
여러개의 모달을 한 페이지에서 관리해야 하기 때문에 리덕스 툴킷을 사용했습니다.

2. 그래서 어떻게 구현하는지?

오늘의 무드를 선택하면 무드카드를 획득하게 되고, 그것이 저희 서비스의 기본화면입니다.
어떤 기능을 사용하든 거의 상시 무드카드가 왼쪽에 자리하고 있습니다.
그리고 오른쪽에는 사용자가 클릭한 모달이 띄워지게 되는것이죠.

리덕스 툴킷의 createSlice를 이용해 모달 슬라이스를 만들었습니다.
모달은 modaltype과 isOpen을 state로 갖고있도록 합니다.
그리고 리듀서로 오픈모달을 만들었습니다.

const initialState = {
  modalType: '',
  isOpen: false,
};
const modalSlice = createSlice({
  name: 'modal',
  initialState,
  reducers: {
    openModal: (state, actions) => {
      const { modalType } = actions.payload;
      state.modalType = modalType;
      state.isOpen = true;
    },
  },
});
export const selectModal = state => state.modal;

store에 리듀서를 추가하는 작업을 해줍니다.

export const store = configureStore({
  reducer: {
    //여기서 리듀서를 관리한다.
    modal: modalSlice,
  },
});

글로벌 모달이라는 컴포넌트에 모달 리스트를 넣어줍니다.
렌더모달 함수가 string으로 모달타입을 받으면 컴포넌트를 돌려줍니다.

const modals = [
  {
    type: 'LetterModal',
    component: <Letter />,
  },
  {
    type: 'TodoModal',
    component: <TodoList />
  },
  .. 생략
];
function GlobalModal() {
  const { modalType, isOpen } = useSelector(selectModal);
  if (!isOpen) return;

  const renderModal = () => {
    // 1. 모달을 찾아서
    const findModal = modals.find((modal) => {
      return modal.type === modalType;
    });
    // 2. 모달의 컴포넌트를 리턴
    return findModal.component;
  };
  return <div>{renderModal()}</div>;
}

모달이 렌더링되는 자리에 글로벌모달 컴포넌트를 심어줍니다.

const Home = () => {
  return (
    <Browser>
      <MoodSelector /> //무드카드
      <GlobalModal /> //모달이 렌더링되는 자리
    </Browser>
  );
};

메뉴 컴포넌트에서 디스패치를 이용해 모달을 핸들링하도록 합니다.

const Nav = () => {
  const dispatch = useDispatch();

  const handleLetterModal = () => {
    dispatch(
      openModal({
        modalType: 'LetterModal',
        isOpen: true,
      })
    );
  };
  const handleTodoModal = () => {
    dispatch(
      openModal({
        modalType: 'TodoModal',
        isOpen: true,
      })
    );
  };

  return (
    <ul>
      <li onClick={handleLetterModal}>
        편지함
      </li>
      <li onClick={handleTodoModal}>
        오늘할일
      </li>
    </ul>
  );
};
  • selectModal을 useSelector로 담아서 찍어보면
    {modalType: 'TodoModal', isOpen: true} 이다!!

0개의 댓글