You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js服务端渲染中能否使用useState?报错排查求助

问题解答

1. Next.js SSR中能否使用useState等React Hooks?

完全可以。在Next.js的页面组件(默认导出的React组件)中,只要遵守React Hook的规则(比如不能在条件/循环中调用、必须在组件顶层调用等),useState、useEffect等Hooks都能正常使用,不管是SSR(getServerSideProps)还是SSG场景。

2. 你的代码报错原因

核心问题:在getServerSideProps中调用React Hooks

getServerSideProps是Next.js提供的服务端数据获取专用函数,它运行在服务端,不属于React组件的渲染上下文,根本不支持调用任何React Hooks(包括你自定义的useFetchTrendingCatagory这类Hook)。你在这个函数里调用自定义Hook,而这些Hook内部肯定用到了useState或其他React Hook,导致React的Hook上下文不存在,抛出Cannot read property 'useState' of null错误。

其他代码问题

  • Hook调用违反规则:页面组件里的useFetchTrendingCatagory等Hook被放在了if/else条件分支中,违反了React Hook的“必须在组件顶层调用”的规则,会导致Hook调用顺序混乱,引发不可预期的bug。
  • getServerSideProps里的拼写错误:context.params.genr应该是context.params.genre;else分支里的genre未定义,需改为context.params.genre。

3. 修正后的代码示例

步骤1:抽离独立的数据请求函数

因为自定义Hook是给React组件用的,服务端数据获取函数里需要直接实现数据请求逻辑,或者把Hook里的请求逻辑抽成独立的函数复用:

// 示例:抽离请求逻辑到单独文件(比如utils/fetchers.js)
export async function fetchTrendingCategory() {
  const res = await fetch('你的趋势电影API地址');
  return res.json();
}

export async function fetchTopRatedCategory() {
  const res = await fetch('你的Top Rated电影API地址');
  return res.json();
}

export async function fetchMovieGenreResults(genre) {
  const res = await fetch(`你的分类电影API地址?genre=${encodeURIComponent(genre)}`);
  return res.json();
}

步骤2:修正页面组件和getServerSideProps

import React, { useState } from "react";
import { useRouter } from "next/router";
import Moviegenreresults from "../../components/Moviegenreresults";
// 导入抽离的请求函数和自定义Hook
import { fetchTrendingCategory, fetchTopRatedCategory, fetchMovieGenreResults } from "../../utils/fetchers";
import useFetchTrendingCatagory from "../../hooks/useFetchTrendingCatagory";
import useFetchTopRatedCatagory from "../../hooks/useFetchTopRatedCatagory";
import useFetchMovieGenreResults from "../../hooks/useFetchMovieGenreResults";

export default function Genre(props) {
  const [myresultsfromhook, setMyresultsfromhook] = useState();
  const [myreturnedmovies, setMyreturnedmovies] = useState();

  const router = useRouter();
  const { genre } = router.query;

  // 把Hook移到组件顶层,遵守Hook规则
  const trendingMovies = useFetchTrendingCatagory();
  const topRatedMovies = useFetchTopRatedCatagory();
  const genreMovies = useFetchMovieGenreResults(genre);

  // 统一处理要展示的电影数据
  let displayMovies;
  if (genre === "Trending") {
    displayMovies = trendingMovies;
  } else if (genre === "Top Rated") {
    displayMovies = topRatedMovies;
  } else {
    displayMovies = genreMovies;
  }

  return (
    <div>
      {/* <Navbar /> */}
      <div>{genre}</div>
      <Moviegenreresults movies={displayMovies} />
    </div>
  );
}

export async function getServerSideProps(context) {
  const { genre } = context.params;
  let results;

  if (genre === "Trending") {
    const data = await fetchTrendingCategory();
    results = data.results;
  } else if (genre === "Top Rated") {
    const data = await fetchTopRatedCategory();
    results = data.results;
  } else {
    const data = await fetchMovieGenreResults(genre);
    results = data.results;
  }

  return {
    props: { results }
  };
}

如果你的场景不需要在服务端预取数据,也可以直接删掉getServerSideProps,让组件通过自定义Hook在客户端获取数据,这样也能解决报错问题。

内容的提问来源于stack exchange,提问作者Iwanttoknow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 12:30:58