TypeError: Cannot read properties of undefined (reading 'map') even though useState() is initialized with array

TypeError: Cannot read properties of undefined (reading 'map') even though useState() is initialized with array

我遇到“TypeError:无法读取未定义的属性(读取 'map')”,即使 useState() 是用数组 初始化的。该错误仅发生在一个组件中。其他组件,我认为,也以相同的方式使用 useState 和 useEffect,不会解决此错误。

import { useState, useEffect } from "react/cjs/react.development";
import * as constants from "../../../../constants";

export default function Keywords(props) {
  const [movieKeywords, setMovieKeywords] = useState([]);

  useEffect(() => {
    const fetchKeywords = async () => {
      const data = await fetch(
        `${constants.TMDB_BASE_PATH}movie/${props.id}/keywords?api_key=${constants.API_KEY}`
      );

      const jsonData = await data.json();
      setMovieKeywords(jsonData.keywords);
      console.log("xdd");
    };

    fetchKeywords();
  }, []);
  return (
    <div className="flex flex-wrap">
      {movieKeywords.map((keyword) => {
        return (
          <div className="border font-oxygen m-1 rounded-xl cursor-pointer text-xs text-gray-300 px-2 py-1">
            <p>{keyword.name}</p>
          </div>
        );
      })}
    </div>
  );
}

如果有人能指出正确的方向,我将很高兴。

在 API 调用和渲染的时间上,您可能只差了几毫秒。一个好的做法是在尝试渲染任何 JSX 之前检查您正在映射的数组是否存在。将您的初始状态设置为 null 并在您的地图行上执行 optional chaining

像这样重构你的组件:

import { useState, useEffect } from "react/cjs/react.development";
import * as constants from "../../../../constants";

export default function Keywords(props) {
  const [movieKeywords, setMovieKeywords] = useState();

  useEffect(() => {
    const fetchKeywords = async () => {
      const data = await fetch(
        `${constants.TMDB_BASE_PATH}movie/${props.id}/keywords?api_key=${constants.API_KEY}`
      );

      const jsonData = await data.json();
      setMovieKeywords(jsonData.keywords);
      console.log("xdd");
    };

    fetchKeywords();
  }, []);
  return (
    <div className="flex flex-wrap">
      {movieKeywords?.map((keyword) => {
        return (
          <div className="border font-oxygen m-1 rounded-xl cursor-pointer text-xs text-gray-300 px-2 py-1">
            <p>{keyword.name}</p>
          </div>
        );
      })}
    </div>
  );
}

注意 movieKeywords?.map,在 movieKeywords 不为 null 之前不会执行映射,这意味着它将等到提取解决并且您的状态已设置。

"jsonData.keywords 不是未定义的。" - 该错误实际上是在通知您确实如此。 setMovieKeywords(jsonData.keywords); 更新状态然后 movieKeywords 未定义且无法访问 .map property/method.

据我所知,您缺少 props.id 作为 useEffectfetch 的依赖项。听起来 props.id 最初不是 API 请求的有效值,您收到未定义的 keywords 响应。

如果您拥有所有必需的参数,您应该只发出 API 请求,并且您的代码应该足够健壮以处理可能无效和错误的响应。

  1. props.id 添加到 useEffect 挂钩的依赖项数组。
  2. 仅在 id 为真时才发出 fetch 请求。
  3. 处理来自 fetch 的可能被拒绝的 Promise。
  4. 处理任何具有未定义值的潜在不良状态更新。

示例:

import { useState, useEffect } from "react/cjs/react.development";
import * as constants from "../../../../constants";

export default function Keywords({ id }) {
  const [movieKeywords, setMovieKeywords] = useState([]);

  useEffect(() => {
    const fetchKeywords = async (id) => {
      try { // <-- (3) use try/catch to handle rejected Promise or other exceptions
        const data = await fetch(
          `${constants.TMDB_BASE_PATH}movie/${id}/keywords?api_key=${constants.API_KEY}`
        );

        const jsonData = await data.json();

        if (jsonData) { // <-- (4) only update state if defined response value
          setMovieKeywords(jsonData.keywords);
        }
      } catch(error) {
        // handle any errors, log, set error state, ignore(?), etc...
      }

      console.log("xdd");
    };

    if (id) { // <-- (2) only fetch if `id` is truthy
      fetchKeywords(id);
    }
  }, [id]); // <-- (1) add `id` as dependency

  return (
    <div className="flex flex-wrap">
      {movieKeywords?.map((keyword) => { // <-- Use Optional Chaining in case `movieKeywords` becomes falsey for any reason
        return (
          <div className="border font-oxygen m-1 rounded-xl cursor-pointer text-xs text-gray-300 px-2 py-1">
            <p>{keyword.name}</p>
          </div>
        );
      })}
    </div>
  );
}