Skip to content

Commit

Permalink
(FE) Refactor react-query and redux (#104)
Browse files Browse the repository at this point in the history
* Add workspace store

* Store workspace information on calling api

* Change call from `useGetWorkspaceQuery` to`workspaceStore`

* Add documentStore

* Change call from `useGetDocumentQuery` to`documentStore`
  • Loading branch information
devleejb authored Jan 25, 2024
1 parent 58b4359 commit b294943
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 24 deletions.
13 changes: 7 additions & 6 deletions frontend/src/components/drawers/WorkspaceDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ import { useSelector } from "react-redux";
import { selectUser } from "../../store/userSlice";
import { MouseEventHandler, useState } from "react";
import ProfilePopover from "../popovers/ProfilePopover";
import { useNavigate, useParams } from "react-router-dom";
import { useGetWorkspaceQuery } from "../../hooks/api/workspace";
import { useNavigate } from "react-router-dom";
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp";
import WorkspaceListPopover from "../popovers/WorkspaceListPopover";
Expand All @@ -28,15 +27,17 @@ import { useCreateDocumentMutation } from "../../hooks/api/workspaceDocument";
import ThemeButton from "../common/ThemeButton";
import PeopleIcon from "@mui/icons-material/People";
import MemberModal from "../modals/MemberModal";
import { selectWorkspace } from "../../store/workspaceSlice";

const DRAWER_WIDTH = 240;

function WorkspaceDrawer() {
const navigate = useNavigate();
const params = useParams();
const userStore = useSelector(selectUser);
const { data: workspace } = useGetWorkspaceQuery(params.workspaceSlug);
const { mutateAsync: createDocument } = useCreateDocumentMutation(workspace?.id || "");
const workspaceStore = useSelector(selectWorkspace);
const { mutateAsync: createDocument } = useCreateDocumentMutation(
workspaceStore.data?.id || ""
);
const [profileAnchorEl, setProfileAnchorEl] = useState<(EventTarget & Element) | null>(null);
const [workspaceListAnchorEl, setWorkspaceListAnchorEl] = useState<
(EventTarget & Element) | null
Expand Down Expand Up @@ -91,7 +92,7 @@ function WorkspaceDrawer() {
<ListItem disablePadding>
<ListItemButton onClick={handleOpenWorkspacePopover}>
<ListItemText
primary={workspace?.title}
primary={workspaceStore.data?.title}
primaryTypographyProps={{
variant: "subtitle1",
noWrap: true,
Expand Down
15 changes: 6 additions & 9 deletions frontend/src/components/modals/MemberModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,7 @@ import {
} from "@mui/material";
import CloseIcon from "@mui/icons-material/Close";
import { useGetWorkspaceUserListQuery } from "../../hooks/api/workspaceUser";
import { useParams } from "react-router-dom";
import {
useCreateWorkspaceInvitationTokenMutation,
useGetWorkspaceQuery,
} from "../../hooks/api/workspace";
import { useCreateWorkspaceInvitationTokenMutation } from "../../hooks/api/workspace";
import { useMemo, useState } from "react";
import { User } from "../../hooks/api/types/user";
import InfiniteScroll from "react-infinite-scroller";
Expand All @@ -27,6 +23,8 @@ import moment, { unitOfTime } from "moment";
import ContentCopyIcon from "@mui/icons-material/ContentCopy";
import clipboard from "clipboardy";
import { useSnackbar } from "notistack";
import { useSelector } from "react-redux";
import { selectWorkspace } from "../../store/workspaceSlice";

interface MemeberModalProps {
open: boolean;
Expand All @@ -35,15 +33,14 @@ interface MemeberModalProps {

function MemeberModal(props: MemeberModalProps) {
const { open, onClose } = props;
const params = useParams();
const { data: workspace } = useGetWorkspaceQuery(params.workspaceSlug);
const workspaceStore = useSelector(selectWorkspace);
const {
data: workspaceUserPageList,
fetchNextPage,
hasNextPage,
} = useGetWorkspaceUserListQuery(workspace?.id);
} = useGetWorkspaceUserListQuery(workspaceStore.data?.id);
const { mutateAsync: createWorkspaceInvitationToken } =
useCreateWorkspaceInvitationTokenMutation(workspace?.id || "");
useCreateWorkspaceInvitationTokenMutation(workspaceStore.data?.id || "");
const userList = useMemo(() => {
return (
workspaceUserPageList?.pages.reduce((prev, page) => {
Expand Down
15 changes: 6 additions & 9 deletions frontend/src/components/modals/ShareModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,25 @@ import { invitationExpiredStringList } from "../../utils/expire";
import { useState } from "react";
import moment, { unitOfTime } from "moment";
import { useParams } from "react-router";
import {
useCreateWorkspaceSharingTokenMutation,
useGetDocumentQuery,
} from "../../hooks/api/workspaceDocument";
import { useCreateWorkspaceSharingTokenMutation } from "../../hooks/api/workspaceDocument";
import { ShareRole } from "../../utils/share";
import clipboard from "clipboardy";
import { useSnackbar } from "notistack";
import ContentCopyIcon from "@mui/icons-material/ContentCopy";
import CloseIcon from "@mui/icons-material/Close";
import { useGetWorkspaceQuery } from "../../hooks/api/workspace";
import { useSelector } from "react-redux";
import { selectDocument } from "../../store/documentSlice";

interface ShareModalProps extends Omit<ModalProps, "children"> {}

function ShareModal(props: ShareModalProps) {
const { ...modalProps } = props;
const params = useParams();
const [shareUrl, setShareUrl] = useState<string | null>(null);
const { data: workspace } = useGetWorkspaceQuery(params.workspaceSlug);
const { data: document } = useGetDocumentQuery(workspace?.id, params.documentId);
const documentStore = useSelector(selectDocument);
const { mutateAsync: createWorkspaceSharingToken } = useCreateWorkspaceSharingTokenMutation(
document?.workspaceId || "",
document?.id || ""
documentStore.data?.workspaceId || "",
documentStore.data?.id || ""
);
const { enqueueSnackbar } = useSnackbar();

Expand Down
14 changes: 14 additions & 0 deletions frontend/src/hooks/api/document.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { useQuery } from "@tanstack/react-query";
import axios from "axios";
import { GetDocumentBySharingTokenResponse } from "./types/document";
import { useDispatch } from "react-redux";
import { useEffect } from "react";
import { setDocumentData } from "../../store/documentSlice";

export const generateGetDocumentBySharingTokenQueryKey = (sharingToken: string) => {
return ["documents", "share", sharingToken];
};

export const useGetDocumentBySharingTokenQuery = (sharingToken?: string | null) => {
const dispatch = useDispatch();
const query = useQuery({
queryKey: generateGetDocumentBySharingTokenQueryKey(sharingToken || ""),
enabled: Boolean(sharingToken),
Expand All @@ -23,5 +27,15 @@ export const useGetDocumentBySharingTokenQuery = (sharingToken?: string | null)
},
});

useEffect(() => {
if (query.data) {
dispatch(setDocumentData(query.data));
}

return () => {
dispatch(setDocumentData(null));
};
}, [dispatch, query.data]);

return query;
};
14 changes: 14 additions & 0 deletions frontend/src/hooks/api/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import {
JoinWorkspaceRequest,
JoinWorkspaceResponse,
} from "./types/workspace";
import { useEffect } from "react";
import { useDispatch } from "react-redux";
import { setWorkspaceData } from "../../store/workspaceSlice";

export const generateGetWorkspaceQueryKey = (workspaceSlug: string) => {
return ["workspaces", workspaceSlug];
Expand All @@ -20,6 +23,7 @@ export const generateGetWorkspaceListQueryKey = () => {
};

export const useGetWorkspaceQuery = (workspaceSlug?: string) => {
const dispatch = useDispatch();
const query = useQuery({
queryKey: generateGetWorkspaceQueryKey(workspaceSlug || ""),
enabled: Boolean(workspaceSlug),
Expand All @@ -32,6 +36,16 @@ export const useGetWorkspaceQuery = (workspaceSlug?: string) => {
},
});

useEffect(() => {
if (query.data) {
dispatch(setWorkspaceData(query.data));
}

return () => {
dispatch(setWorkspaceData(null));
};
}, [dispatch, query.data]);

return query;
};

Expand Down
14 changes: 14 additions & 0 deletions frontend/src/hooks/api/workspaceDocument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import {
GetWorkspaceDocumentResponse,
GetWorkspaceDocumentListResponse,
} from "./types/workspaceDocument";
import { useDispatch } from "react-redux";
import { useEffect } from "react";
import { setDocumentData } from "../../store/documentSlice";

export const generateGetWorkspaceDocumentListQueryKey = (workspaceId: string) => {
return ["workspaces", workspaceId, "documents"];
Expand Down Expand Up @@ -42,6 +45,7 @@ export const useGetWorkspaceDocumentListQuery = (workspaceId?: string) => {
};

export const useGetDocumentQuery = (workspaceId?: string | null, documentId?: string | null) => {
const dispatch = useDispatch();
const query = useQuery({
queryKey: generateGetDocumentQueryKey(workspaceId || "", documentId || ""),
enabled: Boolean(workspaceId && documentId),
Expand All @@ -56,6 +60,16 @@ export const useGetDocumentQuery = (workspaceId?: string | null, documentId?: st
},
});

useEffect(() => {
if (query.data) {
dispatch(setDocumentData(query.data));
}

return () => {
dispatch(setDocumentData(null));
};
}, [dispatch, query.data]);

return query;
};

Expand Down
37 changes: 37 additions & 0 deletions frontend/src/store/documentSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { createSlice } from "@reduxjs/toolkit";
import type { PayloadAction } from "@reduxjs/toolkit";
import { RootState } from "./store";

export interface Document {
id: string;
workspaceId: string;
yorkieDocumentId: string;
title: string;
content?: string;
createdAt: Date;
updatedAt: Date;
}

export interface DocumentState {
data: Document | null;
}

const initialState: DocumentState = {
data: null,
};

export const documentSlice = createSlice({
name: "document",
initialState,
reducers: {
setDocumentData: (state, action: PayloadAction<Document | null>) => {
state.data = action.payload;
},
},
});

export const { setDocumentData } = documentSlice.actions;

export const selectDocument = (state: RootState) => state.document;

export default documentSlice.reducer;
4 changes: 4 additions & 0 deletions frontend/src/store/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import storage from "redux-persist/lib/storage";
import { persistReducer } from "redux-persist";
import authSlice from "./authSlice";
import userSlice from "./userSlice";
import workspaceSlice from "./workspaceSlice";
import documentSlice from "./documentSlice";

const reducers = combineReducers({
// Persistence
Expand All @@ -13,6 +15,8 @@ const reducers = combineReducers({
// Volatile
user: userSlice,
editor: editorSlice,
workspace: workspaceSlice,
document: documentSlice,
});

const persistConfig = {
Expand Down
35 changes: 35 additions & 0 deletions frontend/src/store/workspaceSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { createSlice } from "@reduxjs/toolkit";
import type { PayloadAction } from "@reduxjs/toolkit";
import { RootState } from "./store";

export interface Workspace {
id: string;
title: string;
slug: string;
updatedAt: Date;
createdAt: Date;
}

export interface WorkspaceState {
data: Workspace | null;
}

const initialState: WorkspaceState = {
data: null,
};

export const workspaceSlice = createSlice({
name: "workspace",
initialState,
reducers: {
setWorkspaceData: (state, action: PayloadAction<Workspace | null>) => {
state.data = action.payload;
},
},
});

export const { setWorkspaceData } = workspaceSlice.actions;

export const selectWorkspace = (state: RootState) => state.workspace;

export default workspaceSlice.reducer;

0 comments on commit b294943

Please sign in to comment.