Next.js应用构建报错:React Hook使用违规问题求助
React Hook报错解决方案(Next.js Pages Router场景)
一、核心问题:getStaticProps中调用"use"前缀函数报错
原因
- 你的
useFetchParisTimeISG只是普通异步数据获取函数,没有使用任何React Hook API(如useState/useEffect),不符合React Hook定义却用了use开头命名,触发ESLint的Hook规则校验。 getStaticProps是Next.js的构建/服务端专用函数,不属于React组件或自定义Hook,本身就不能调用任何React Hook。
解决方案:将fetch逻辑封装为普通工具函数
- 修改工具函数:去掉
use前缀,移除无用的React导入,保留异步逻辑:
// hooks/SSR/ISR/fetchParisTime.js export default async function fetchParisTime() { const response = await fetch( `https://timeapi.io/api/Time/current/zone?timeZone=Europe/Paris` ); return await response.json(); }
- 在getStaticProps中调用该工具函数:
// pages/SSG/paristimeisg.js import fetchParisTime from "../../hooks/SSR/ISR/fetchParisTime"; export async function getStaticProps() { const mytime = await fetchParisTime(); return { props: { mytime }, revalidate: 60 }; } export default function paristimeisg({ mytime }) { console.log("This is my time", mytime); return ( <div> Hello <h2>{mytime.milliSeconds}</h2> </div> ); }
二、额外问题:客户端组件中调用报错
原因
- React组件名称必须大写开头,你的
timeforISG是小写,ESLint会认为它不是合法的React组件。 - 原函数是异步函数,即使去掉
use前缀,也不能直接在组件渲染阶段调用(会导致Promise直接渲染);同时,合法的React Hook不能是异步函数,不能用async function useXXX()定义。
解决方案:封装为合法的自定义Hook(客户端数据获取)
- 修改组件名称为大写开头,同时封装支持异步请求的自定义Hook:
// hooks/useParisTime.js import { useState, useEffect } from "react"; export default function useParisTime() { const [timeData, setTimeData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchData = async () => { try { const response = await fetch( `https://timeapi.io/api/Time/current/zone?timeZone=Europe/Paris` ); const data = await response.json(); setTimeData(data); } catch (err) { setError(err); } finally { setLoading(false); } }; fetchData(); }, []); return { timeData, loading, error }; }
- 在客户端组件中使用该Hook:
// pages/SSG/TimeforISG.js 注意组件名大写开头 import useParisTime from "../../hooks/useParisTime"; export default function TimeforISG() { const { timeData, loading, error } = useParisTime(); if (loading) return <div>加载中...</div>; if (error) return <div>获取数据失败:{error.message}</div>; return <div>{timeData.milliSeconds}</div>; }
内容的提问来源于stack exchange,提问作者Time2learn
相关产品推荐
相关产品推荐

