1
1
import Link from "next/link" ;
2
- import { useEffect , useState } from "react" ;
2
+ import { useCallback , useEffect , useState , useSyncExternalStore } from "react" ;
3
3
import styles from "../../../styles/components/Header.module.scss" ;
4
4
import Hamburger from "./Hamburger" ;
5
5
import { useRouter } from "next/router" ;
6
6
import Image from "next/image" ;
7
7
import { useSession } from "next-auth/react" ;
8
8
import getCookieData from "../../../lib/getCookieData" ;
9
9
10
- function Header ( ) {
10
+ export default function Header ( ) {
11
11
const [ menuOpen , setMenuOpen ] = useState ( false ) ;
12
12
const [ active , setActive ] = useState ( "/" ) ;
13
+
14
+ const isMobile = useMediaQuery ( "only screen and (max-width : 900px)" ) ;
15
+ const router = useRouter ( ) ;
16
+
13
17
const { data : session } = useSession ( ) ;
14
18
const { data : cookieData } = getCookieData ( session ) ;
15
19
16
- function toggleMenu ( ) {
17
- setMenuOpen ( ! menuOpen ) ;
18
- menuOpen
19
- ? document . body . classList . remove ( "body-scroll-lock" )
20
- : document . body . classList . add ( "body-scroll-lock" )
20
+ const toggleMenu = ( ) => {
21
+ setMenuOpen ( prev => ! prev ) ;
22
+ document . body . classList . toggle ( "body-scroll-lock" , isMobile && ! menuOpen )
21
23
}
22
24
23
- const router = useRouter ( ) ;
24
25
25
26
useEffect ( ( ) => {
26
27
setActive ( router . pathname ) ;
27
- } , [ router . pathname ] ) ;
28
+
29
+ const removeScrollLock = ( ) =>
30
+ document . body . classList . toggle ( "body-scroll-lock" , isMobile && menuOpen )
31
+
32
+ window . addEventListener ( 'resize' , removeScrollLock )
33
+
34
+ return ( ) => window . removeEventListener ( "resize" , removeScrollLock )
35
+ } , [ router . pathname , menuOpen , isMobile ] ) ;
28
36
29
37
return (
30
38
< nav className = { styles . navbar } >
@@ -92,8 +100,6 @@ function Header() {
92
100
) ;
93
101
}
94
102
95
- export default Header ;
96
-
97
103
const headerItems = [
98
104
{
99
105
href : "/about" ,
@@ -112,3 +118,27 @@ const headerItems = [
112
118
name : "Events" ,
113
119
} ,
114
120
] ;
121
+
122
+ function useMediaQuery ( query : string ) {
123
+ const subscribe = useCallback (
124
+ ( callback : ( ) => void ) => {
125
+ const matchMedia = window . matchMedia ( query ) ;
126
+
127
+ matchMedia . addEventListener ( "change" , callback ) ;
128
+ return ( ) => {
129
+ matchMedia . removeEventListener ( "change" , callback ) ;
130
+ } ;
131
+ } ,
132
+ [ query ]
133
+ ) ;
134
+
135
+ const getSnapshot = ( ) => {
136
+ return window . matchMedia ( query ) . matches ;
137
+ } ;
138
+
139
+ const getServerSnapshot = ( ) => {
140
+ throw Error ( "useMediaQuery is a client-only hook" ) ;
141
+ } ;
142
+
143
+ return useSyncExternalStore ( subscribe , getSnapshot , getServerSnapshot ) ;
144
+ }
0 commit comments