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

时间:2018-09-27 03:03:36

标签: javascript reactjs

我正在关注ReactJS AJAX and APIs tutorial。我在Spring中编写了一个简单的API,然后在http://localhost:8080上使用了一个React组件来使用该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是不确定的?我遵循了对similar question的回答,在第12行初始化了items,并在第48行检查了items,无济于事。

我该如何解决?

3 个答案:

答案 0 :(得分:1)

这很可能是由于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>
      );
    }
  }

希望有帮助!

答案 1 :(得分:1)

感谢@DacreDenny的建议:)

第27行:items: result.items。该行期望响应包含一个名为“ items”的对象。

但是我的API仅返回对象数组。所以我将行更改为

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

答案 2 :(得分:0)

这样做吧。避免在渲染中使用if循环,而应直接使用&&运算符或三元运算符来管理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>
  );

此外,对象中的make键最初包含空值,因此您无法将其分配为键。相反,您可以做的是尝试从后端为数组中的对象生成唯一的ID,或者使用下面的类似方法

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

请问我有错字问题,因为我正在用手机应答