mirror of
https://github.com/DefectingCat/DefectingCat.github.io
synced 2025-07-15 08:41:37 +00:00
Fix menu list on mobile
* add ahooks library * add useAppDispatch and useAppSelector hooks * move out router event handle from useEffect * fix router events off
This commit is contained in:
6
app/hooks.ts
Normal file
6
app/hooks.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
|
||||
import type { RootState, AppDispatch } from './store';
|
||||
|
||||
// Use throughout your app instead of plain `useDispatch` and `useSelector`
|
||||
export const useAppDispatch = () => useDispatch<AppDispatch>();
|
||||
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
|
@ -1,4 +1,4 @@
|
||||
import { FC, MouseEvent, useEffect } from 'react';
|
||||
import { FC, MouseEvent, useRef } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Image,
|
||||
@ -13,9 +13,8 @@ import {
|
||||
Button,
|
||||
} from '@chakra-ui/react';
|
||||
import UseAnimations from 'react-useanimations';
|
||||
import menu2 from 'react-useanimations/lib/menu2';
|
||||
import menu3 from 'react-useanimations/lib/menu3';
|
||||
import { FiHome, FiArchive, FiUser, FiSun, FiMoon } from 'react-icons/fi';
|
||||
import Link from 'next/link';
|
||||
import useGetColors from '../lib/hooks/useGetColors';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
@ -40,28 +39,68 @@ const menu = [
|
||||
},
|
||||
];
|
||||
|
||||
interface MenuListProps {
|
||||
boxBg: string;
|
||||
handleMenuClick: (
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
e: MouseEvent<HTMLDivElement, globalThis.MouseEvent>,
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
path: string
|
||||
) => void;
|
||||
}
|
||||
const MenuList: FC<MenuListProps> = ({ boxBg, handleMenuClick }) => {
|
||||
return (
|
||||
<Flex
|
||||
as="nav"
|
||||
mt={['1.5rem', null]}
|
||||
flexFlow={['column']}
|
||||
py={['1rem', null, 'unset']}
|
||||
px={['2rem', '4rem', 'unset']}
|
||||
bg={[boxBg, null, 'unset']}
|
||||
shadow={['card', null, 'unset']}
|
||||
>
|
||||
{menu.map((item) => {
|
||||
return (
|
||||
<Flex
|
||||
onClick={(e) => handleMenuClick(e, item.path)}
|
||||
href={item.path}
|
||||
key={item.id}
|
||||
as="a"
|
||||
alignItems="center"
|
||||
justifyContent={['unset', null, 'space-between']}
|
||||
fontSize={['18', null, '22']}
|
||||
my={['0.5rem', null, '0.5rem']}
|
||||
cursor="pointer"
|
||||
>
|
||||
<Icon as={item.icon} mr={['2.5rem', null, 'unset']} />
|
||||
<Text>{item.name}</Text>
|
||||
</Flex>
|
||||
);
|
||||
})}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
const NavBar: FC = () => {
|
||||
const router = useRouter();
|
||||
|
||||
const [isLargerThan768] = useMediaQuery('(min-width: 768px)');
|
||||
const { isOpen, onToggle } = useDisclosure({ defaultIsOpen: true });
|
||||
const { isOpen, onToggle } = useDisclosure({ defaultIsOpen: false });
|
||||
|
||||
const { colorMode, toggleColorMode } = useColorMode();
|
||||
|
||||
const { boxBg, bioColor, textColor, headingColor } = useGetColors();
|
||||
|
||||
useEffect(() => {
|
||||
if ((isOpen && !isLargerThan768) || (!isOpen && isLargerThan768))
|
||||
onToggle();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isLargerThan768]);
|
||||
|
||||
const iconRef = useRef<HTMLDivElement>(null);
|
||||
// Switch pages
|
||||
const handleMenuClick = (
|
||||
e: MouseEvent<HTMLDivElement, globalThis.MouseEvent>,
|
||||
path: string
|
||||
) => {
|
||||
e.preventDefault();
|
||||
!isLargerThan768 && onToggle();
|
||||
!isLargerThan768 &&
|
||||
// Click the animate icon.
|
||||
(iconRef.current?.children[0] as HTMLDivElement).click();
|
||||
router.push(path);
|
||||
};
|
||||
|
||||
@ -124,36 +163,19 @@ const NavBar: FC = () => {
|
||||
|
||||
{/* Menu */}
|
||||
<Box mx={['-2rem', '-4rem', 'unset']}>
|
||||
<Collapse in={isOpen} animateOpacity>
|
||||
<Flex
|
||||
as="nav"
|
||||
mt={['1.5rem', null]}
|
||||
flexFlow={['column']}
|
||||
py={['1rem', null, 'unset']}
|
||||
px={['2rem', '4rem', 'unset']}
|
||||
bg={[boxBg, null, 'unset']}
|
||||
shadow={['card', null, 'unset']}
|
||||
>
|
||||
{menu.map((item) => {
|
||||
return (
|
||||
<Flex
|
||||
onClick={(e) => handleMenuClick(e, item.path)}
|
||||
href={item.path}
|
||||
key={item.id}
|
||||
as="a"
|
||||
alignItems="center"
|
||||
justifyContent={['unset', null, 'space-between']}
|
||||
fontSize={['18', null, '22']}
|
||||
my={['0.5rem', null, '0.5rem']}
|
||||
cursor="pointer"
|
||||
>
|
||||
<Icon as={item.icon} mr={['2.5rem', null, 'unset']} />
|
||||
<Text>{item.name}</Text>
|
||||
</Flex>
|
||||
);
|
||||
})}
|
||||
</Flex>
|
||||
</Collapse>
|
||||
{/* Mobile menu */}
|
||||
<Box
|
||||
as={Collapse}
|
||||
in={isOpen}
|
||||
animateOpacity
|
||||
display={[null, null, 'none']}
|
||||
>
|
||||
<MenuList boxBg={boxBg} handleMenuClick={handleMenuClick} />
|
||||
</Box>
|
||||
{/* Desktop menu */}
|
||||
<Box display={['none', 'none', 'block']}>
|
||||
<MenuList boxBg={boxBg} handleMenuClick={handleMenuClick} />
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
@ -161,13 +183,14 @@ const NavBar: FC = () => {
|
||||
position={'absolute'}
|
||||
top={'1.5rem'}
|
||||
right={'1rem'}
|
||||
onClick={onToggle}
|
||||
ref={iconRef}
|
||||
>
|
||||
<UseAnimations
|
||||
reverse={isOpen}
|
||||
size={40}
|
||||
animation={menu2}
|
||||
speed={1.5}
|
||||
animation={menu3}
|
||||
speed={2}
|
||||
onClick={onToggle}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
|
@ -4,7 +4,7 @@ import { Box, Flex, Heading, Text, Link } from '@chakra-ui/react';
|
||||
import { AllPostsData } from '../lib/posts';
|
||||
import { Icon, Image } from '@chakra-ui/react';
|
||||
import { FiCalendar, FiTag } from 'react-icons/fi';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useAppDispatch } from '../app/hooks';
|
||||
import { setFromPath } from '../features/router/routerSlice';
|
||||
import { useRouter } from 'next/router';
|
||||
import useGetColors from '../lib/hooks/useGetColors';
|
||||
@ -14,7 +14,7 @@ interface Props {
|
||||
}
|
||||
|
||||
const PostCard: FC<Props> = ({ post }) => {
|
||||
const dispatch = useDispatch();
|
||||
const dispatch = useAppDispatch();
|
||||
const router = useRouter();
|
||||
|
||||
const goToPost: MouseEventHandler<HTMLAnchorElement> = (e) => {
|
||||
|
@ -5,6 +5,7 @@ export interface RouterState {
|
||||
}
|
||||
|
||||
const initialState: RouterState = {
|
||||
// Record the from path when into the post page.
|
||||
fromPath: '',
|
||||
};
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
"@emotion/styled": "^11",
|
||||
"@giscus/react": "^1.0.1",
|
||||
"@reduxjs/toolkit": "^1.6.2",
|
||||
"ahooks": "^2.10.12",
|
||||
"autoprefixer": "^10.3.7",
|
||||
"date-fns": "^2.25.0",
|
||||
"framer-motion": "^5.0.2",
|
||||
|
@ -26,24 +26,23 @@ function MyApp({ Component, pageProps }: AppPropsWithLayout) {
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const handleRouteChange = (
|
||||
url: string,
|
||||
{ shallow }: { shallow: 'with' | 'without' }
|
||||
) => {
|
||||
console.log(
|
||||
`App is changing to ${url} ${
|
||||
shallow ? 'with' : 'without'
|
||||
} shallow routing`
|
||||
);
|
||||
};
|
||||
const handleStart = () => {
|
||||
NProgress.start();
|
||||
};
|
||||
const handleStop = () => {
|
||||
NProgress.done();
|
||||
};
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (
|
||||
url: string,
|
||||
{ shallow }: { shallow: 'with' | 'without' }
|
||||
) => {
|
||||
console.log(
|
||||
`App is changing to ${url} ${
|
||||
shallow ? 'with' : 'without'
|
||||
} shallow routing`
|
||||
);
|
||||
};
|
||||
const handleStart = () => {
|
||||
NProgress.start();
|
||||
};
|
||||
const handleStop = () => {
|
||||
NProgress.done();
|
||||
};
|
||||
|
||||
router.events.on('routeChangeStart', handleRouteChange);
|
||||
router.events.on('routeChangeStart', handleStart);
|
||||
router.events.on('routeChangeStart', handleStop);
|
||||
@ -52,8 +51,8 @@ function MyApp({ Component, pageProps }: AppPropsWithLayout) {
|
||||
// from the event with the `off` method:
|
||||
return () => {
|
||||
router.events.off('routeChangeStart', handleRouteChange);
|
||||
router.events.on('routeChangeStart', handleStart);
|
||||
router.events.on('routeChangeStart', handleStop);
|
||||
router.events.off('routeChangeStart', handleStart);
|
||||
router.events.off('routeChangeStart', handleStop);
|
||||
};
|
||||
}, [router.events]);
|
||||
|
||||
|
@ -33,11 +33,11 @@ import { useRouter } from 'next/router';
|
||||
import Footer from '../../components/Footer';
|
||||
import { Giscus } from '@giscus/react';
|
||||
import { RootState } from '../../app/store';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { cleanFromPath } from '../../features/router/routerSlice';
|
||||
import CopyButton from '../../components/post/CopyButton';
|
||||
import useGetColors from '../../lib/hooks/useGetColors';
|
||||
import PostImage from '../../components/post/PostImage';
|
||||
import { useAppSelector, useAppDispatch } from '../../app/hooks';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const paths = await getAllPostSlugs();
|
||||
@ -57,8 +57,8 @@ export const getStaticProps: GetStaticProps = async ({ params }) => {
|
||||
};
|
||||
|
||||
const Post = ({ postData }: InferGetStaticPropsType<typeof getStaticProps>) => {
|
||||
const fromPath = useSelector((state: RootState) => state.router.fromPath);
|
||||
const dispatch = useDispatch();
|
||||
const fromPath = useAppSelector((state: RootState) => state.router.fromPath);
|
||||
const dispatch = useAppDispatch();
|
||||
const router = useRouter();
|
||||
|
||||
const goBack = () => {
|
||||
|
48
yarn.lock
48
yarn.lock
@ -2,6 +2,14 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@ahooksjs/use-request@^2.8.13":
|
||||
version "2.8.13"
|
||||
resolved "https://registry.npmjs.org/@ahooksjs/use-request/-/use-request-2.8.13.tgz#5ace53859feb6b4fe9ebcbf2e72982bb9b7db383"
|
||||
integrity sha512-zGSOwGNy6fTudvBcLJ8Ly7DwacEGzQS06fGe1b1mEPWTsK/R6y8ItIbtE2RXTeMoCpbxagamMWo5ZDJkJlmZ6Q==
|
||||
dependencies:
|
||||
lodash.debounce "^4.0.8"
|
||||
lodash.throttle "^4.1.1"
|
||||
|
||||
"@babel/code-frame@7.12.11":
|
||||
version "7.12.11"
|
||||
resolved "https://registry.npmmirror.com/@babel/code-frame/download/@babel/code-frame-7.12.11.tgz?cache=0&sync_timestamp=1633554562995&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40babel%2Fcode-frame%2Fdownload%2F%40babel%2Fcode-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f"
|
||||
@ -1290,6 +1298,22 @@ aggregate-error@^3.0.0:
|
||||
clean-stack "^2.0.0"
|
||||
indent-string "^4.0.0"
|
||||
|
||||
ahooks@^2.10.12:
|
||||
version "2.10.12"
|
||||
resolved "https://registry.npmjs.org/ahooks/-/ahooks-2.10.12.tgz#e8cab653039434279e69569a8342c602b3545dab"
|
||||
integrity sha512-X3nZwr6+CSi1XjGyd/tQU1vF11mNaP4Bo0pdEdUL2ksBURQl0QZvDeUMrKBYHAStq7852P20ycVgu405XxDlFg==
|
||||
dependencies:
|
||||
"@ahooksjs/use-request" "^2.8.13"
|
||||
"@types/js-cookie" "^2.2.6"
|
||||
dayjs "^1.9.1"
|
||||
intersection-observer "^0.7.0"
|
||||
js-cookie "^2.2.1"
|
||||
lodash.debounce "^4.0.8"
|
||||
lodash.isequal "^4.5.0"
|
||||
lodash.throttle "^4.1.1"
|
||||
resize-observer-polyfill "^1.5.1"
|
||||
screenfull "^5.0.0"
|
||||
|
||||
ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4:
|
||||
version "6.12.6"
|
||||
resolved "https://registry.nlark.com/ajv/download/ajv-6.12.6.tgz?cache=0&sync_timestamp=1631470912358&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fajv%2Fdownload%2Fajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
|
||||
@ -2187,7 +2211,7 @@ date-fns@^2.25.0:
|
||||
resolved "https://registry.npmmirror.com/date-fns/download/date-fns-2.25.0.tgz?cache=0&sync_timestamp=1633421929609&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fdate-fns%2Fdownload%2Fdate-fns-2.25.0.tgz#8c5c8f1d958be3809a9a03f4b742eba894fc5680"
|
||||
integrity sha1-jFyPHZWL44CamgP0t0LrqJT8VoA=
|
||||
|
||||
dayjs@^1.10.4:
|
||||
dayjs@^1.10.4, dayjs@^1.9.1:
|
||||
version "1.10.7"
|
||||
resolved "https://registry.nlark.com/dayjs/download/dayjs-1.10.7.tgz?cache=0&sync_timestamp=1631266651008&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdayjs%2Fdownload%2Fdayjs-1.10.7.tgz#2cf5f91add28116748440866a0a1d26f3a6ce468"
|
||||
integrity sha1-LPX5Gt0oEWdIRAhmoKHSbzps5Gg=
|
||||
@ -3532,6 +3556,11 @@ internal-slot@^1.0.3:
|
||||
has "^1.0.3"
|
||||
side-channel "^1.0.4"
|
||||
|
||||
intersection-observer@^0.7.0:
|
||||
version "0.7.0"
|
||||
resolved "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.7.0.tgz#ee16bee978db53516ead2f0a8154b09b400bbdc9"
|
||||
integrity sha512-Id0Fij0HsB/vKWGeBe9PxeY45ttRiBmhFyyt/geBdDHBYNctMRTE3dC1U3ujzz3lap+hVXlEcVaB56kZP/eEUg==
|
||||
|
||||
invariant@^2.2.4:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.nlark.com/invariant/download/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
|
||||
@ -3965,6 +3994,16 @@ locate-path@^5.0.0:
|
||||
dependencies:
|
||||
p-locate "^4.1.0"
|
||||
|
||||
lodash.debounce@^4.0.8:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
|
||||
|
||||
lodash.isequal@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
||||
integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
|
||||
|
||||
lodash.merge@^4.6.2:
|
||||
version "4.6.2"
|
||||
resolved "https://registry.npm.taobao.org/lodash.merge/download/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||
@ -3985,6 +4024,11 @@ lodash.sortby@^4.7.0:
|
||||
resolved "https://registry.npm.taobao.org/lodash.sortby/download/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
|
||||
integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
|
||||
|
||||
lodash.throttle@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
|
||||
integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=
|
||||
|
||||
lodash.truncate@^4.4.2:
|
||||
version "4.4.2"
|
||||
resolved "https://registry.nlark.com/lodash.truncate/download/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
|
||||
@ -5682,7 +5726,7 @@ scheduler@^0.20.2:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
screenfull@^5.1.0:
|
||||
screenfull@^5.0.0, screenfull@^5.1.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.npmmirror.com/screenfull/download/screenfull-5.2.0.tgz?cache=0&sync_timestamp=1635923453416&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fscreenfull%2Fdownload%2Fscreenfull-5.2.0.tgz#6533d524d30621fc1283b9692146f3f13a93d1ba"
|
||||
integrity sha1-ZTPVJNMGIfwSg7lpIUbz8TqT0bo=
|
||||
|
Reference in New Issue
Block a user