Gau*_*ang 9 reactjs next.js next.js13
我正在尝试使用 NextJS 13.4.7 创建一个应用程序,并使用useMediaQuery钩子来检测视图是否是移动的。我的组件不是服务器组件,但我不断收到client-only挂钩错误。现在我的客户端组件是服务器组件的一部分,但从文档来看,它似乎是允许的。我错过了什么吗?下面是代码,
"use client";
import { useContext, useState, useEffect } from "react";
import PageDataContext from "@/contexts/PageDataContext";
import useMediaQuery from "@/hooks/useMediaQuery";
import { motion } from "framer-motion";
export default function Header() {
const content = useContext(PageDataContext);
const isSmallDevice = useMediaQuery("only screen and (max-width : 991px)");
const [hideNav, setHideNav] = useState(isSmallDevice);
const { home: homeContent } = content;
const { navigation: navigationContent } = content;
const { name } = homeContent;
const [firstName, lastName] = name.split(" ");
const onTheRight = { x: "100%" };
const inTheCenter = { x: 0 };
const onTheLeft = { x: "-100%" };
const transition = { duration: 0.6, ease: "easeInOut" };
const variants = {
open: { opacity: 1, x: "0%" },
closed: { opacity: 0, x: "100%" },
};
const toggleSideNav = () => {
setHideNav(!hideNav);
};
useEffect(() => {
setHideNav(isSmallDevice);
}, [isSmallDevice]);
return (
<header id="site_header" className="header">
<div className="header-content clearfix">
<div className="text-logo">
<a href="/">
<div className="logo-symbol">{firstName[0].toUpperCase()}</div>
<div className="logo-text">
{firstName} <span>{lastName}</span>
</div>
</a>
</div>
<motion.div
animate={hideNav ? "closed" : "open"}
variants={variants}
style={{
position: "fixed",
width: "100%",
height: "calc(100% - 52px)",
top: "52px",
left: "auto",
}}
>
<div className="site-nav">
<ul className="leven-classic-menu site-main-menu">
{navigationContent.map((item, idx) => (
<li className="menu-item" key={"header_key_" + idx}>
<a href={item.url}>{item.title}</a>
</li>
))}
</ul>
</div>
</motion.div>
<a className="menu-toggle mobile-visible" onClick={toggleSideNav}>
<i className="fa fa-bars"></i>
</a>
</div>
</header>
);
}
Run Code Online (Sandbox Code Playgroud)
我遇到了同样的问题。这是因为 useMediaQuery 同时渲染服务器端和客户端。即使您给出“use client”指令,如果它以某种方式在 ssr 所在的位置工作,也会发生此错误。
作为解决方案,您可以创建自定义挂钩并通过动态导入使用该挂钩:
自定义挂钩示例:
"use client";
import useMediaQuery from "@/hooks/useMediaQuery";
const useDevice = () => {
const isMobile = useMediaQuery("only screen and (max-width : 767px)");
const isTablet = useMediaQuery(
"only screen and (min-width : 768px) and (max-width : 1024px)"
);
const isDesktop = useMediaQuery(
"only screen and (min-width : 1025px) and (max-width : 2379px)"
);
const isDesktopLarge = useMediaQuery("only screen and (min-width : 2380px)");
return { isMobile, isTablet, isDesktop, isDesktopLarge };
};
export default useDevice;
Run Code Online (Sandbox Code Playgroud)
用法:
"use client";
const useDevice = dynamic(() => import("@/app/hooks/useDevice"), {
ssr: false
});
export default function Header() {
const device = useDevice();
console.log(device?.isDesktop)
...
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1006 次 |
| 最近记录: |