使用 next.js 使用动态 url 获取数据时,find(...) 未定义

find(...) is undefined when fetching data with dynamic url using next.js

当我在主页中获取数据时,一切都如我所愿 但是当我使用相同的代码但使用动态 url 在另一个文件夹中获取数据时,我在尝试对数组使用方法时遇到错误。当我 console.log 获取数据时,我得到了与主页相同的数组

当我删除 Link 并且只想查看 book.title 时,它起作用了。但是当我想从资源中获取数据时出现错误。

mainpage.js
const [data, setData] = useState(null);
const [isLoading, setLoading] = useState(false);

useEffect(() => {
  setLoading(true);
  fetch('https://gnikdroy.pythonanywhere.com/api/book')
    .then((res) => res.json())
    .then((data) => {
      setData(data);
      setLoading(false);
    });
}, []);

return(
       <div>
        {data.results.map((book, index) => (
          <div key={index}>
            <h1>{book.title}</h1>
            <Link href={`/reader/${book.id}`} passHref>
              <h2>
                {
                  book.resources.find(
                    ({ type }) => type === 'application/epub+zip'
                  ).uri
                }
              </h2>
            </Link>
          </div>
        ))}
      </div>
)
searchPage.js
const router = useRouter();
const { name } = router.query;
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);

useEffect(() => {
  setLoading(true);
  fetch(`https://gnikdroy.pythonanywhere.com/api/book/?search=${name}`)
    .then((res) => res.json())
    .then((data) => {
      setData(data);
      setLoading(false);
      console.log(data);
    });
}, []);

return(
      <div>
        {data.results.map((book, index) => (
          <div key={index}>
            <h1>{book.title}</h1>
            <Link href={`/reader/${book.id}`} passHref>
              <h2>
                {
                  book.resources.find(
                    ({ type }) => type === 'application/epub+zip'
                  ).uri
                }
              </h2>
            </Link>
          </div>
        ))}
      </div>
)

我的 console.log 在 searchPage.js

中获取

您的响应数据有时没有获取资源字段。
这就是 book.resources 可以未定义(或)为空的原因。

您可以轻松使用Optional Changing(?.)

替换:

{
   book.resources?.find(
     ({ type }) => type === 'application/epub+zip'
   )?.uri || ''
}

除了 Wu Woo 的回答,当考虑 React 如何渲染你的代码时,

首先将执行 return,然后仅在页面加载时执行 useEffect,因为 useEffect 依赖数组中没有值。

所以在您的场景中,您在初始页面加载时有 data = null。所以当渲染下面的代码时,因为 data = null data.results 不能使用 Arrays.map().

然后将执行 useEffect 并在其中设置 API 调用中的值 return 并将该值设置为数据。

为避免渲染未定义错误,您必须确保 data.results 不等于 null/undefined,并且当存在 data.results 时渲染您想要的内容。

您可以通过以下方式实现。

  1. 可选的链接运算符 (?.) 作为 Wu Woo 的回答,当引用或函数可能是 undefined or null 时,它简化了通过连接对象访问值的过程。那么当 book.resources 等于 null/undefined.

    时就不会报上面的错误了
  2. 仅当 data.resultsbook.resources 有值时才渲染,否则不会像下面那样。

      // Here conditionally check whether there is value for data?.results and if so render this.
     {data?.results && data.results.map((book, index) => (
     <div key={index}>
       <h1>{book.title}</h1>
       <Link href={`/reader/${book.id}`} passHref>
         <h2>
           {/* Here also conditionally check whether there is value for book?.resources and if so render this. */}
           { book?.resources &&
             book.resources.find(
               ({ type }) => type === 'application/epub+zip'
             ).uri
           }
         </h2>
       </Link>
     </div>
     ))}