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

Next.js _app的getInitialProps返回undefined致JSON解析报错

问题现象

在_app页面通过getInitialProps读取cookies,将侧边栏尺寸值传递给下游组件用于设置元素宽度时,传递值始终为undefined,在AsideLeft组件初始化state执行JSON.parse时报错:Unexpected token u in JSON at position 0。

根因分析
  • 异步方法未加await:App.getInitialProps(appContext)是异步返回Promise的方法,原代码未加await就直接展开返回值,导致返回结构异常,自定义字段无法正确注入组件props
  • Props传递层级错误:getInitialProps返回的自定义字段initialAsideLeftHandler和pageProps是平级关系,原代码仅将pageProps展开传给Layout组件,外层的自定义字段根本没有传入下游
  • 无兜底逻辑:首次访问页面时asideLeftHandlercookie尚未生成,parseCookies(req)拿不到对应字段,直接传递undefined给下游组件;JSON.parse(undefined)执行时会先将值转为字符串"undefined",首字符为u,直接触发解析报错
  • 重复解析:cookie本身是字符串格式,若上游已经完成JSON解析为对象,下游再次执行JSON.parse会把对象转成字符串"[object Object]"再解析,同样会触发报错
修复代码

修改_app.tsx

// _app.tsx -> page 
import App, { AppProps } from 'next/app'
// 按你实际使用的parseCookies引入路径调整
import { parseCookies } from 'nookies'

// 侧边栏默认尺寸,作为cookie不存在/损坏时的兜底值
const DEFAULT_ASIDE_HANDLER = {
  x: 0,
  y: 0,
  width: 240,
  height: 0
}

function MyApp({ Component, pageProps, initialAsideLeftHandler }: AppProps & { initialAsideLeftHandler: typeof DEFAULT_ASIDE_HANDLER }) {
    return ( 
        <Layout initialAsideLeftHandler={initialAsideLeftHandler}> 
            <Component {...pageProps} /> 
        </Layout>   
    ); 
}

MyApp.getInitialProps = async (appContext) => { 
    // 必须加await获取真实的pageProps返回值
    const pageProps = await App.getInitialProps(appContext); 
    const { req } = appContext.ctx; 
    const cookies = parseCookies(req); 

    let asideHandler = DEFAULT_ASIDE_HANDLER
    if (cookies.asideLeftHandler) {
      try {
        asideHandler = JSON.parse(cookies.asideLeftHandler)
      } catch (err) {
        // cookie值格式损坏时回退到默认值
        asideHandler = DEFAULT_ASIDE_HANDLER
      }
    }

    return { 
        ...pageProps, 
        initialAsideLeftHandler: asideHandler
    }; 
}
export default MyApp;

修改AsideLeft组件

// asideLeftHandler.tsx -> component 
const DEFAULT_ASIDE_HANDLER = {
  x: 0,
  y: 0,
  width: 240,
  height: 0
}

function AsideLeft({ initialAsideLeftHandler = DEFAULT_ASIDE_HANDLER }) {
  const router = useRouter();
  // 上游已经传递解析完成的对象,不需要重复执行JSON.parse
  const [asideLeftHandler, setAsideLeftHandler] = useState(initialAsideLeftHandler);

  useEffect(() => {
    Cookie.set("asideLeftHandler", JSON.stringify(asideLeftHandler), { expires: 7 });
  }, [asideLeftHandler]);

  return (
    <Resizeable width={asideLeftHandler.width}>
      {/* 其余业务代码 */}
    </Resizeable>
  )
}

提示:若使用Next.js 13+ App Router模式,getInitialProps仅在Pages Router下生效,App Router中需在服务端组件调用cookies()方法读取cookie值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 02:21:15