使用Next.js时出现TypeError: Cannot read property 'useState' of null如何解决?
修复Next.js中useState触发"TypeError: Cannot read property 'useState' of null"错误
错误信息
TypeError: Cannot read property 'useState' of null
出错代码
import { useState } from "react"; import { getLimitedTutors } from "utils/api/tutors"; const [tutorLimit, setTutorLimit] = useState(10); // 错误发生位置 export async function getStaticProps() { const { data: tutor } = await getLimitedTutors(tutorLimit ? tutorLimit : 10); return { props: { tutors: tutor.data, }, }; } // 导出组件部分
getLimitedTutors 实现代码
export function getLimitedTutors(limit) { return cms.get(`/tutors?pagination[start]=0&pagination[limit]=${limit}&populate=*`); }
问题原因
- useState调用位置违规:React Hook(包括useState)必须在React组件的顶层作用域内调用,不能在组件外部、服务端函数(如
getStaticProps)或非组件逻辑中使用,你直接在模块顶层声明useState,违反了Hook的使用规则。 - 跨作用域变量引用错误:
getStaticProps是Next.js在构建/服务端阶段运行的函数,和客户端组件渲染完全隔离,根本无法访问组件的状态变量tutorLimit。
修复方案
方案1:将useState移至组件内部
把状态声明放到导出的React组件内部,getStaticProps中使用固定值初始化数据:
import { useState } from "react"; import { getLimitedTutors } from "utils/api/tutors"; // 构建时获取初始数据 export async function getStaticProps() { const { data: tutor } = await getLimitedTutors(10); return { props: { tutors: tutor.data, }, }; } // React组件内部使用useState export default function TutorsPage({ tutors }) { const [tutorLimit, setTutorLimit] = useState(10); // 组件渲染逻辑 return ( <div> {/* 你的组件内容 */} </div> ); }
方案2:前端动态调整显示数量(推荐)
如果需要通过前端交互切换导师显示数量,可在组件内部对初始获取的数据做过滤,避免重复请求:
import { useState } from "react"; import { getLimitedTutors } from "utils/api/tutors"; // 构建时获取足够多的初始数据 export async function getStaticProps() { const { data: tutor } = await getLimitedTutors(20); return { props: { allTutors: tutor.data, }, }; } export default function TutorsPage({ allTutors }) { const [tutorLimit, setTutorLimit] = useState(10); // 根据状态过滤显示的数据 const displayedTutors = allTutors.slice(0, tutorLimit); return ( <div> <button onClick={() => setTutorLimit(prev => prev + 5)}>加载更多</button> {displayedTutors.map(tutor => ( <div key={tutor.id}>{tutor.attributes.name}</div> ))} </div> ); }
方案3:动态请求不同数量的数据(用SWR)
如果必须根据前端状态动态请求不同数量的数据,使用SWR实现客户端数据请求:
import { useState } from "react"; import useSWR from 'swr'; import { getLimitedTutors } from "utils/api/tutors"; // 自定义请求函数 const fetcher = (limit) => getLimitedTutors(limit).then(res => res.data); export default function TutorsPage() { const [tutorLimit, setTutorLimit] = useState(10); // 根据tutorLimit动态请求数据 const { data, error } = useSWR(tutorLimit, fetcher); if (error) return <div>加载失败</div>; if (!data) return <div>加载中...</div>; return ( <div> <button onClick={() => setTutorLimit(prev => prev + 5)}>加载更多</button> {data.data.map(tutor => ( <div key={tutor.id}>{tutor.attributes.name}</div> ))} </div> ); }
内容的提问来源于stack exchange,提问作者Shifty
相关产品推荐
相关产品推荐

