React Fetch返回Unusable __proto__对象

时间:2017-06-15 22:17:33

标签: arrays reactjs fetch

我正在尝试访问以下api端点的special_abilities数组:http://www.dnd5eapi.co/api/monsters/1

这是我的容器组件:

import React, { Component } from 'react'
import { Link } from 'react-router';
import MonsterSpecialAbilities from '../components/MonsterSpecialAbilities'

class MonstersContainer extends Component {
  constructor(props) {
    super(props)
    this.state = {
      monster: {},
      number: Math.floor((Math.random())*325)
    }
    this.handleRandomClick = this.handleRandomClick.bind(this)
  }

  componentDidMount() {
    fetch(`http://www.dnd5eapi.co/api/monsters/${this.state.number}`)
      .then(response => response.json())
      .then(responseData => {
        this.setState({ monster: responseData })
      })
  }

  render() {
    let spec_abilities;
    spec_abilities = this.state.monster.special_abilities.map((ab) => {
      return(
        <MonsterSpecialAbilities
          desc={ab.desc}
        />
      )
    })
    return(
      <div>
        {this.state.monster.name}
        {spec_abilities}
      </div>
    )
  }
}

export default MonstersContainer

现在.map函数会破坏我的组件,我收到控制台错误:Uncaught TypeError: this.state.monster.special_abilities.map is not a function。我尝试访问this.state.monster.special_abilities[0]来尝试访问该数组,但这会返回null,这让我相信它是一个无效的数组。

我尝试创建一个州名monster_special_ability并按以下方式手动设置数组:

  componentDidMount() {
    fetch(`http://www.dnd5eapi.co/api/monsters/${this.state.number}`)
      .then(response => response.json())
      .then(responseData => {
        this.setState({ monster: responseData })
        this.setState({ monster_special_abilities: responseData.special_abilities })
      })
  }

我已经尝试将调试器放入setState函数,并在控制台中输入responseData.special_abilities返回我想要的数组,但是在设置状态后,似乎该数组不可用(它变成原型:对象)

2 个答案:

答案 0 :(得分:0)

将您的怪物更改为初始状态下的null,并将渲染更改为:

render() {
    if (!this.state.monster) {
      return <div> Loading monster...</div>;
    }

    const spec_abilities = this.state.monster.special_abilities.map(ab =>
        <MonsterSpecialAbilities desc={ab.desc} />
    )

    return (
      <div>
        {this.state.monster.name}
        {spec_abilities}
      </div>
    )
  }

如果您需要将monster作为对象,则可以检查是否已设置special_abilitiesmonster

答案 1 :(得分:0)

在反应组件中使用fetch时的常见做法是使用加载状态。最初将其设置为false,一旦解析了fetch,将其设置为true。如果加载状态为true,则只渲染组件。因此,您的最终代码应如下所示:

&#13;
&#13;
class MonstersContainer extends Component {
  constructor(props) {
    super(props)
    this.state = {
      isDataLoaded: false,
      monster: {},
      number: Math.floor((Math.random())*325)
    }
    this.handleRandomClick = this.handleRandomClick.bind(this)
  }

  componentDidMount() {
    fetch(`http://www.dnd5eapi.co/api/monsters/${this.state.number}`)
      .then(response => response.json())
      .then(responseData => {
        this.setState({ 
          isDataLoaded: true,
          monster: responseData 
        })
      }).catch(e => console.log(e));
  }

  render() {
    const { isDataLoaded, monster } = this.state;
    const monsterProps = { isDataLoaded, monster };
    return <Monsters {...monsterProps} />
  }
}

function MonsterSpecialAbilities(desc) {
  return <div>desc</div>
}

function Monsters(props) {
   const {isDataLoaded, monster} = props;
   let spec_abilities;
    
    if (isDataLoaded && monster.special_abilities) {
      spec_abilities = monster.special_abilities.map((ab) =>
        <MonsterSpecialAbilities
          desc={ab.desc}
        />
      );    
    }

    return (isDataLoaded && spec_abilities && monster.name) ? (
      <div>
        {monster.name}
        {spec_abilities}
      </div>
    ): <div>loading monster data...</div>;
   
}
&#13;
&#13;
&#13;

jsbin上查看。

请注意,提取可能会失败,您还需要对其执行某些操作。您可以添加另一个名为errorMessage的状态,该状态显示错误消息。在您的情况下,请确保您的主机在http而不是https上运行,因为使用https获取时获取网址不起作用。

相关问题