开发者问题收集

TypeError:无法读取未定义的属性“map”

2018-09-27
16897

我正在遵循 ReactJS AJAX 和 API 教程 。我在 Spring 中编写了一个简单的 API,然后编写了一个 React 组件以在 http://localhost:8080 上使用该 API。API 当前返回两个项目的列表,如下所示:

[
    {brand:"Asus", make:"AAA"},
    {brand:"Acer", make:"BBB"}
]

这是我的组件的样子:

import React from 'react';
import ReactDOM from 'react-dom';

import { environment } from '../environment/environment';

export class ComputerList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      error: null,
      isLoaded: false,
      items: [
        {brand: null, make: null}
      ]
    };
  }

  componentDidMount() {
    fetch("http://localhost:8080/computers")
    .then(res => res.json())
    .then(
      (result) => {
        // correctly displays the results
        console.log(result);
        this.setState({
          isLoaded: true,
          items: result.items
        });
      },
      (error) => {
        this.setState({
          isLoaded: true,
          error
        });
      }
    )
  }

  render() {
    const { error, isLoaded, items } = this.state;

    if(error) {
      return(<div>Error: {error.message}</div>);
    }
    else if(!isLoaded) {
      return(<div>Loading...</div>);
    }
    else if(items) {
      console.log(items);
      // error here: cannot read property "map" of undefined
      // because this.state.items is undefined somehow?
      return(
        <ul>
          {items.map(item => (
            <li key={item.make}>{item.brand} {item.make}</li>
          ))}
        </ul>
      );
    }
  }
}

在第 24 行,结果已成功检索并记录。

但在第 54 行,当我尝试将每个结果映射到 <li> 项目时,会抛出 TypeError ,因为 items 不知何故未定义?我按照 类似问题 的答案,在第 12 行初始化 items ,并检查第 48 行的 items ,但无济于事。

我该如何解决这个问题?

3个回答

这可能是由于 items 的类型不是数组,这就是为什么 map() 方法无法定义的原因。

为了获得更强大的 render() 方法,您可以将 else if(items) { 替换为 else if(Array.isArray(items)) { ,这应该可以防止出现您看到的错误消息:

render() {
    const { error, isLoaded, items } = this.state;

    if(error) {
      return(<div>Error: {error.message}</div>);
    }
    else if(!isLoaded) {
      return(<div>Loading...</div>);
    }
    else if(Array.isArray(items)) { // <-- update here
      console.log(items);
      // error here: cannot read property "map" of undefined
      // because this.state.items is undefined somehow?
      return(
        <ul>
          {items.map(item => (
            <li key={item.make}>{item.brand} {item.make}</li>
          ))}
        </ul>
      );
    }
  }

希望对您有所帮助!

Dacre Denny
2018-09-27

感谢@DacreDenny 的建议 :)

第 27 行: items: result.items 。此行要求响应包含一个名为“items”的对象。

但我的 API 只返回一个对象数组。因此我将行更改为

第 27 行: items: result 。这会将整个数组保存到 state.items 。然后可以正确映射和渲染。

Jason
2018-09-27

只需这样做。避免在渲染中使用 if 循环,而是直接在 return 中使用 && 运算符或三元运算符来管理 if 检查

  return(
    <ul>
      {!isLoaded && <div>Loading...</div>}
       {error && !isLoaded && <div>Error: {error.message}</div>)}
      {!isLoaded && items && items.map(item => (
        <li key={item.make}>{item.brand} {item.make}</li>
      ))}
    </ul>
  );

此外,您在对象中制作的键最初包含空值,因此您无法将其指定为键。相反,您可以尝试从后端为数组中的对象生成唯一 ID,或者使用类似下面的内容

 return(
    <ul>
      {items && items.map((item, index) => (
        <li key={"key"+index}>{item.brand} {item.make}</li>
      ))}
    </ul>
  );

抱歉,我打错了,因为我是用手机接听的

Hemadri Dasari
2018-09-27