chore: add useNavigateTo hook

This commit is contained in:
steven 2023-09-24 21:21:34 +08:00
parent f78b072bb8
commit 159dfc9446
9 changed files with 47 additions and 45 deletions

View File

@ -1,6 +1,6 @@
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom"; import useNavigateTo from "@/hooks/useNavigateTo";
import { shortcutService } from "../services"; import { shortcutService } from "../services";
import useUserStore from "../stores/v1/user"; import useUserStore from "../stores/v1/user";
import { showCommonDialog } from "./Alert"; import { showCommonDialog } from "./Alert";
@ -16,7 +16,7 @@ interface Props {
const ShortcutActionsDropdown = (props: Props) => { const ShortcutActionsDropdown = (props: Props) => {
const { shortcut } = props; const { shortcut } = props;
const { t } = useTranslation(); const { t } = useTranslation();
const navigate = useNavigate(); const navigateTo = useNavigateTo();
const currentUser = useUserStore().getCurrentUser(); const currentUser = useUserStore().getCurrentUser();
const [showEditDialog, setShowEditDialog] = useState<boolean>(false); const [showEditDialog, setShowEditDialog] = useState<boolean>(false);
const [showQRCodeDialog, setShowQRCodeDialog] = useState<boolean>(false); const [showQRCodeDialog, setShowQRCodeDialog] = useState<boolean>(false);
@ -34,7 +34,7 @@ const ShortcutActionsDropdown = (props: Props) => {
}; };
const gotoAnalytics = () => { const gotoAnalytics = () => {
navigate(`/shortcut/${shortcut.id}#analytics`); navigateTo(`/shortcut/${shortcut.id}#analytics`);
}; };
return ( return (

View File

@ -1,5 +1,4 @@
import { ReactNode, useEffect, useRef } from "react"; import { ReactNode, useEffect, useRef, useState } from "react";
import useToggle from "../../hooks/useToggle";
import Icon from "../Icon"; import Icon from "../Icon";
interface Props { interface Props {
@ -11,14 +10,14 @@ interface Props {
const Dropdown: React.FC<Props> = (props: Props) => { const Dropdown: React.FC<Props> = (props: Props) => {
const { trigger, actions, className, actionsClassName } = props; const { trigger, actions, className, actionsClassName } = props;
const [dropdownStatus, toggleDropdownStatus] = useToggle(false); const [dropdownStatus, setDropdownStatus] = useState(false);
const dropdownWrapperRef = useRef<HTMLDivElement>(null); const dropdownWrapperRef = useRef<HTMLDivElement>(null);
useEffect(() => { useEffect(() => {
if (dropdownStatus) { if (dropdownStatus) {
const handleClickOutside = (event: MouseEvent) => { const handleClickOutside = (event: MouseEvent) => {
if (!dropdownWrapperRef.current?.contains(event.target as Node)) { if (!dropdownWrapperRef.current?.contains(event.target as Node)) {
toggleDropdownStatus(false); setDropdownStatus(false);
} }
}; };
@ -35,7 +34,7 @@ const Dropdown: React.FC<Props> = (props: Props) => {
const handleToggleDropdownStatus = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => { const handleToggleDropdownStatus = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
e.stopPropagation(); e.stopPropagation();
toggleDropdownStatus(); setDropdownStatus(!dropdownStatus);
}; };
return ( return (

View File

@ -0,0 +1,20 @@
import { NavigateOptions, useNavigate } from "react-router-dom";
const useNavigateTo = () => {
const navigateTo = useNavigate();
const navigateToWithViewTransition = (to: string, options?: NavigateOptions) => {
const document = window.document as any;
if (!document.startViewTransition) {
navigateTo(to, options);
} else {
document.startViewTransition(() => {
navigateTo(to, options);
});
}
};
return navigateToWithViewTransition;
};
export default useNavigateTo;

View File

@ -1,21 +0,0 @@
import { useCallback, useState } from "react";
// Parameter is the boolean, with default "false" value
const useToggle = (initialState = false): [boolean, (nextState?: boolean) => void] => {
// Initialize the state
const [state, setState] = useState(initialState);
// Define and memorize toggler function in case we pass down the comopnent,
// This function change the boolean value to it's opposite value
const toggle = useCallback((nextState?: boolean) => {
if (nextState !== undefined) {
setState(nextState);
} else {
setState((state) => !state);
}
}, []);
return [state, toggle];
};
export default useToggle;

View File

@ -2,13 +2,14 @@ import { useColorScheme } from "@mui/joy";
import { isEqual } from "lodash-es"; import { isEqual } from "lodash-es";
import { useEffect } from "react"; import { useEffect } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Outlet, useNavigate } from "react-router-dom"; import { Outlet } from "react-router-dom";
import useNavigateTo from "@/hooks/useNavigateTo";
import { UserSetting_ColorTheme } from "@/types/proto/api/v2/user_setting_service"; import { UserSetting_ColorTheme } from "@/types/proto/api/v2/user_setting_service";
import Header from "../components/Header"; import Header from "../components/Header";
import useUserStore from "../stores/v1/user"; import useUserStore from "../stores/v1/user";
const Root: React.FC = () => { const Root: React.FC = () => {
const navigate = useNavigate(); const navigateTo = useNavigateTo();
const { setMode } = useColorScheme(); const { setMode } = useColorScheme();
const { i18n } = useTranslation(); const { i18n } = useTranslation();
const userStore = useUserStore(); const userStore = useUserStore();
@ -18,7 +19,7 @@ const Root: React.FC = () => {
useEffect(() => { useEffect(() => {
if (!currentUser) { if (!currentUser) {
navigate("/auth", { navigateTo("/auth", {
replace: true, replace: true,
}); });
return; return;

View File

@ -69,7 +69,7 @@ const Home: React.FC = () => {
</div> </div>
<FilterView /> <FilterView />
{loadingState.isLoading ? ( {loadingState.isLoading ? (
<div className="py-12 w-full flex flex-row justify-center items-center opacity-80"> <div className="py-12 w-full flex flex-row justify-center items-center opacity-80 dark:text-gray-500">
<Icon.Loader className="mr-2 w-5 h-auto animate-spin" /> <Icon.Loader className="mr-2 w-5 h-auto animate-spin" />
loading loading
</div> </div>

View File

@ -4,7 +4,8 @@ import copy from "copy-to-clipboard";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useLoaderData, useNavigate } from "react-router-dom"; import { useLoaderData } from "react-router-dom";
import useNavigateTo from "@/hooks/useNavigateTo";
import { showCommonDialog } from "../components/Alert"; import { showCommonDialog } from "../components/Alert";
import AnalyticsView from "../components/AnalyticsView"; import AnalyticsView from "../components/AnalyticsView";
import CreateShortcutDialog from "../components/CreateShortcutDialog"; import CreateShortcutDialog from "../components/CreateShortcutDialog";
@ -23,7 +24,7 @@ interface State {
const ShortcutDetail = () => { const ShortcutDetail = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const navigate = useNavigate(); const navigateTo = useNavigateTo();
const shortcutId = (useLoaderData() as Shortcut).id; const shortcutId = (useLoaderData() as Shortcut).id;
const shortcut = shortcutService.getShortcutById(shortcutId) as Shortcut; const shortcut = shortcutService.getShortcutById(shortcutId) as Shortcut;
const currentUser = useUserStore().getCurrentUser(); const currentUser = useUserStore().getCurrentUser();
@ -56,7 +57,7 @@ const ShortcutDetail = () => {
style: "danger", style: "danger",
onConfirm: async () => { onConfirm: async () => {
await shortcutService.deleteShortcutById(shortcut.id); await shortcutService.deleteShortcutById(shortcut.id);
navigate("/", { navigateTo("/", {
replace: true, replace: true,
}); });
}, },

View File

@ -2,7 +2,8 @@ import { Button, Input } from "@mui/joy";
import React, { FormEvent, useEffect, useState } from "react"; import React, { FormEvent, useEffect, useState } from "react";
import { toast } from "react-hot-toast"; import { toast } from "react-hot-toast";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link } from "react-router-dom";
import useNavigateTo from "@/hooks/useNavigateTo";
import useWorkspaceStore from "@/stores/v1/workspace"; import useWorkspaceStore from "@/stores/v1/workspace";
import * as api from "../helpers/api"; import * as api from "../helpers/api";
import useLoading from "../hooks/useLoading"; import useLoading from "../hooks/useLoading";
@ -10,7 +11,7 @@ import useUserStore from "../stores/v1/user";
const SignIn: React.FC = () => { const SignIn: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const navigate = useNavigate(); const navigateTo = useNavigateTo();
const userStore = useUserStore(); const userStore = useUserStore();
const workspaceStore = useWorkspaceStore(); const workspaceStore = useWorkspaceStore();
const [email, setEmail] = useState(""); const [email, setEmail] = useState("");
@ -20,7 +21,7 @@ const SignIn: React.FC = () => {
useEffect(() => { useEffect(() => {
if (userStore.getCurrentUser()) { if (userStore.getCurrentUser()) {
return navigate("/", { return navigateTo("/", {
replace: true, replace: true,
}); });
} }
@ -52,7 +53,7 @@ const SignIn: React.FC = () => {
await api.signin(email, password); await api.signin(email, password);
const user = await userStore.fetchCurrentUser(); const user = await userStore.fetchCurrentUser();
if (user) { if (user) {
navigate("/", { navigateTo("/", {
replace: true, replace: true,
}); });
} else { } else {

View File

@ -2,7 +2,8 @@ import { Button, Input } from "@mui/joy";
import React, { FormEvent, useEffect, useState } from "react"; import React, { FormEvent, useEffect, useState } from "react";
import { toast } from "react-hot-toast"; import { toast } from "react-hot-toast";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link } from "react-router-dom";
import useNavigateTo from "@/hooks/useNavigateTo";
import useWorkspaceStore from "@/stores/v1/workspace"; import useWorkspaceStore from "@/stores/v1/workspace";
import * as api from "../helpers/api"; import * as api from "../helpers/api";
import useLoading from "../hooks/useLoading"; import useLoading from "../hooks/useLoading";
@ -10,7 +11,7 @@ import useUserStore from "../stores/v1/user";
const SignUp: React.FC = () => { const SignUp: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const navigate = useNavigate(); const navigateTo = useNavigateTo();
const userStore = useUserStore(); const userStore = useUserStore();
const workspaceStore = useWorkspaceStore(); const workspaceStore = useWorkspaceStore();
const [email, setEmail] = useState(""); const [email, setEmail] = useState("");
@ -21,13 +22,13 @@ const SignUp: React.FC = () => {
useEffect(() => { useEffect(() => {
if (userStore.getCurrentUser()) { if (userStore.getCurrentUser()) {
return navigate("/", { return navigateTo("/", {
replace: true, replace: true,
}); });
} }
if (!workspaceStore.setting.enableSignup) { if (!workspaceStore.setting.enableSignup) {
return navigate("/auth", { return navigateTo("/auth", {
replace: true, replace: true,
}); });
} }
@ -59,7 +60,7 @@ const SignUp: React.FC = () => {
await api.signup(email, nickname, password); await api.signup(email, nickname, password);
const user = await userStore.fetchCurrentUser(); const user = await userStore.fetchCurrentUser();
if (user) { if (user) {
navigate("/", { navigateTo("/", {
replace: true, replace: true,
}); });
} else { } else {