【问题标题】:React Hooks Not Allowing Me to Display Single Objects After Fetch CallReact Hooks 不允许我在 Fetch 调用后显示单个对象
【发布时间】:2020-08-24 13:29:03
【问题描述】:

我在 React Hooks 项目中使用 fetch 调用标准 JSON 文件。 (我正在模拟一个使用 JSON-Server 读取本地 json 文件的服务器)

在我的主函数中,我调用了一个变量和一个函数,就像任何普通的 React Hook 一样,并将它设置为一个空数组,因为我正在使用 fetch 调用 API 数据。

let [items, setItems] = useState([]);

然后我对我的模拟服务器进行实际的 fetch 调用

    const fetchItems = async () => {
        const url = "http://localhost:3002/learn";
        const response = await fetch(url);
        items = await response.json();
        setItems(items);
        console.log(items[0].title);
    }

console.log(items[0].title) 实际上确实返回了正确的值。

如果我想显示所有结果,甚至可以使用以下方法。

{items.map((item) => 
   <img src={item.source} alt={item.title} title={item.title}  className="img-fluid mx-auto d-block" />
)}

但是,一旦我想在退货中显示单个值,就会收到一条错误消息: “TypeError:无法读取未定义的属性‘源’” 我使用的代码,最初只是为了测试,与我之前的console.log 完全相同。

<img src={items[0].source} alt={items[0].title} title={items[0].title}  className="img-fluid mx-auto d-block" />

我是否错过了让我在退货中使用获取的信息的重要步骤?

如果我在同一个组件上硬编码我的 JSON 数据,它会起作用。我觉得它与获取有关。 我在看这个问题,它很相似,但不是一回事。我也在使用钩子,也没有使用 axios。 Can't display data after fetch

更新: JSON 文件如下所示:

{
    "learn": [
      {
        "id": 1,
        "title": "Angular JS",
        "source": "./images/logo-angular-js.png"
      },
      {
        "id": 2,
        "title": "Firebase",
        "source": "./images/logo-firebase.png"
      },
      {
        "id": 3,
        "title": "GraphQL",
        "source": "./images/logo-graphql.png"
      }
    ]
}

【问题讨论】:

  • 请分享items数组。它看起来像什么?有什么叫source的吗?
  • items = await response.json(); 不要这样做。仅使用状态设置器设置状态。不要直接改变状态。
  • 我这样做的唯一原因是,如果我像 let items = await response.json(); 那样做,我的结果是不确定的。
  • 在您的fetchItems 通话中尝试items = (await response.json()).learn;
  • 如果这没有帮助,请尝试在 fetch 调用中记录整个 items 对象并将其内容发布到此处。除了您当前正在记录的第一项之外,该数组可能至少包含一个空值。

标签: javascript json reactjs fetch react-hooks


【解决方案1】:

在您的第一次渲染中,items 的长度为 0,因此 items[0] 将是 undefined。您可能会尝试在第一个项目加载之前进行渲染。

在尝试访问 items[0].source 等之前检查是否定义了 items[0]

function YourComponent() {
  const [items, setItems] = useState([]);

  useEffect(() => {
    fetchItems();
  }, []);

  const fetchItems = async () => {
    const url = "http://localhost:3002/learn";
    const response = await fetch(url);
    items = await response.json();
    setItems(items);
    console.log(items[0].title);
  }

  if (!items.length) {
    return null;
  }

  return (
    <img 
      src={items[0].source}
      alt={items[0].title}
      title={items[0].title}
      className="img-fluid mx-auto d-block" /> 
  );
}

在第一次渲染时,这不会导致任何输出。在调用setItems 之后,组件将重新渲染,这一次(如果设置了项目),它将渲染您的项目。

【讨论】:

  • 该死,这确实有效。好的,只是让我知道发生了什么事。如果进行 fetch 调用,组件首先呈现,然后在旧的 componentDidMount(useEffect) 上,发生 fetch 调用,然后重新呈现。这对于为什么硬编码的对象会立即工作而不是获取信息是有道理的。硬编码信息立即与原始渲染一起渲染。这真的感觉像是一个基准。太感谢了。我真的对 StackOverflow 失去了信心。
  • 您能解释一下为什么.map 有效吗? .map 中是否有内置的 continue 功能?
  • 这是因为对一个空数组执行map 会生成另一个空数组,并且渲染一个空的元素数组会产生不渲染任何内容的效果。
猜你喜欢
  • 1970-01-01
  • 2021-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-14
  • 2022-01-09
  • 1970-01-01
  • 2019-09-18
相关资源
最近更新 更多