访问JavaScript数组将返回“未定义”

时间:2019-05-17 14:26:23

标签: javascript arrays reactjs

我正在用纯Reactjs构建一个简单的应用程序。我遇到问题的组件是应该通过映射一个以前通过从外部API提取一些数据来填充的数组来呈现许多按钮的组件。该数组填充在类方法中,结果最终复制到另一个数组中,该数组是组件状态的一部分

当我在组件的render方法上console.log数组的内容时,一切看起来都很好。但是,如果我尝试通过其索引打印特定元素,则控制台上会打印“ undefined”。结果,地图功能无法呈现所有所需的按钮。

在设法填充数组的过程中,我设法找到了不同的文档,但是到目前为止,没有一篇文章表明我在做任何根本上错误的事情。至少我看不到。

状态存储一个空数组,以componentWillMount方法开头,并在componentWillMount方法内,调用API来获取数据并按照以下说明更新数组:

this.state = {
      resources: []
}

getAPIavaiableResources(api_resource) {
    let buttonsArray = []
    fetch(api_resource)
      .then(response => response.json())
      .then(data => {
        for (let i in data) {
          buttonsArray.push({id: i, name: i, url: data[i]})
        }
      }).catch(error => console.log(error))

    this.setState({resources: buttonsArray})
}

componentWillMount() {
    this.getAPIavaiableResources(ROOT_RESOURCE)
}

render() {
    const { resources } = this.state;
    console.log(resources)
    console.log(resources[0])

    return (
      <div className="buttons-wrapper">
        {
          resources.map(resource => {
            return <Button
                      key={resource.id}
                      text={resource.name} 
                      onClick={this.handleClick} 
                    />
          })
        }
      </div>
    )
}

这是通过render方法打印到控制台上的内容。

[]
0: {id: "people", name: "people", url: "https://swapi.co/api/people/"}
1: {id: "planets", name: "planets", url: "https://swapi.co/api/planets/"}
2: {id: "films", name: "films", url: "https://swapi.co/api/films/"}
3: {id: "species", name: "species", url: "https://swapi.co/api/species/"}
4: {id: "vehicles", name: "vehicles", url: "https://swapi.co/api/vehicles/"}
5: {id: "starships", name: "starships", url: "https://swapi.co/api/starships/"}
length: 6
__proto__: Array(0)

有人可以看到我在做什么吗?我要推送一个对象是因为我确实想要一个对象数组,尽管Javascript中的数组也是对象。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

您当前的实现方式是在获取数据之前先设置状态,然后在api调用返回时将状态更改。 React无法分辨您何时进行更改,因此不知道要重新渲染。仅当您调用setState(或当它收到新的道具)时,它才知道要重新渲染。

相反,请等到有了数据,然后再使用填充的数组调用setState。

getAPIavaiableResources(api_resource) {
  fetch(api_resource)
    .then(response => response.json())
    .then(data => {
      let buttonsArray = []
      for (let i in data) {
        buttonsArray.push({id: i, name: i, url: data[i]})
      }
      this.setState({resources: buttonsArray})
    }).catch(error => console.log(error))
}

componentDidMount() {
    this.getAPIavaiableResources(ROOT_RESOURCE)
}

上面的示例还更新了代码,以使用componentDidMount而不是componentWillMount。 componentWillMount已弃用,无论如何都不打算用于这种情况。

答案 1 :(得分:0)

当前,您正在设置状态,而无需等待承诺被解决。为此,请在this.setState({resources: buttonsArray})循环之后将for移动。

此外,您可以有条件地渲染组件,直到通过执行以下操作从远程资源获得所需的内容为止:

render () {
  const { resources } = this.state;
  return resources.length
    ? (
      <div>Your content...</div>
    )
    : null // or some loader
}