开发者问题收集

nextjs-TypeError:无法读取未定义的属性(读取‘title’)

2023-02-03
3178

我正在使用 nextjs 作为框架,尝试使用 slug 显示标题

我在 [slug].js 文件中的代码是:

import React, { useState } from 'react'
import { useRouter } from 'next/router'
const slug = ({proDetail}) => {
  const router = useRouter();
  const { slug } = router.query
  console.log(proDetail[slug].title)
  return (<div>title:{proDetail[slug].title}</div>)
}
export default slug

在上面的代码(第 3 行)中,proDetails 是 _app.js 中的一个对象,它作为 [slug].js 的 prop 给出

export default function App({ Component, pageProps }) {
   var proDetail = {
     s1: {  title: "Tomato", disc:"lorem" },
     s2: {  title: "Pepper", disc:"lorem" },
     s3: {  title: "Lettuce", disc:"lorem" },
     s4: {  title: "Carrot", disc:"lorem" },
     s5: {  title: "Radish", disc:"lorem" }
   }
    return <>
       <Component proDetail={proDetail} {...pageProps}/>
     </>
  }

错误图片

我希望我的标题能够在对象中为不同的 url http://localhost:3000/s{i} 显示相应的标题(其中“i”是从 1 到 5 的数字,因为我的 proDetail 中只有 s1 到 s5 的键对象)

我的动机是如果我更改 URL 但出现 TypeError: 无法读取未定义的属性(读取“title”) 如果我使用 proDetail["s2"].title 代替 proDetail[slug].title 那么我的标题就会显示在网页上,但这只显示 key:s2 的标题

import React, { useState } from 'react'
import { useRouter } from 'next/router'

const slug = ({proDetail}) => {
  const router = useRouter();
  const { slug } = router.query
  return (<div>title:{proDetail["s2"].title}</div>)
}

title display http://localhost:3000/s(anyValue)

但显示 title: Pepper 甚至会出现在 http://localhost:3000/s(anyValue) 中,因为我已经更改了我的 HTML。

如何解决此 TypeError:无法读取未定义的属性(读取“title”)。我不想为每个标题创建单独的页面,而是想使用 slug。

我理解控制台语句和 html 在获取定义的 slug 值之前被渲染,但如何克服这个错误

2个回答
import React from 'react'
import { useRouter } from 'next/router'

const slug =(({proDetail}) => {
  const router = useRouter();
  let {slug} =router.query
  console.log(slug)
  return (<div>title:
    {slug === undefined ? 'Loading...' : JSON.stringify(proDetail[slug].title)} 
    </div>)
})
export default slug

我明白,只有当我的 slug 未定义时,我才能评估 proDetail[slug].title

B M PAVAN
2023-02-04

您使用 useEffect 的方式几乎是正确的,但是您需要验证 slug 值是否为空。

useEffect(() => {
   if(slug) {
      console.log(proDetail[slug].title);
   }
}, [slug])

原因是当 slug 不可用时, useEffect 也会在第一次渲染时触发。因此,您得到了同样的错误。


您还可以使用在 next/router 包中定义的 router.isReady ,如下所示

import React, { useState, useEffect } from 'react'
import { useRouter } from 'next/router'
const Slug = ({proDetail}) => {
  const [slugValue, setSlugValue] = useState();
  const router = useRouter();
  const { slug } = router.query;
   
  useEffect(() => {
    if(router.isReady) {
       setSlugValue(slug);
    }
  }, [router.isReady]);

  if(!slugValue) {
     return null;
  }

  return (<div>title:{proDetail[slugValue]?.title}</div>)
}
export default Slug

此逻辑可以帮助您克服在某些情况下仍然允许空的 slug 的问题。

请注意,我将您的组件名称从 slug 更改为 Slug ,以避免您在组件中也使用的变量重复。

Nick Vu
2023-02-04