返回映射over响应值的选项

时间:2017-12-15 04:05:02

标签: javascript reactjs

嘿大家所以我正在向谷歌API提出请求并提取一些数据。最初,我的状态值只是一个空对象,从ajax请求我希望状态值用setState填充。

然后,在另一个方法中,我将获取状态数据并映射项目并为该数组中的每个元素返回一个选项。奇怪的是,在我开始返回我映射的值之前,我就是console.loging值,它们正是我想要的值。但是,当我返回一个带有该值的选项时,我的选择中仍然没有任何内容。

任何人都可以详细说明我可能做错了吗?

constructor() {
  super();
  this.state = {
  };

componentDidMount() {
  let URL = is the url with my api key (it works)
  axios.get(URL)
  .then((data) => {
      console.log("data" + data);
      this.setState({
        googleFonts: data
      })
  })
  .catch((err) => {
    console.log(err);
    this.setState({
      errors: err
    })
  })
}

renderFonts() {
  let data = this.state.googleFonts.data.items;
  return data.map((font, index) => {
    console.log(font.family);
    return (
     <ul>
       <li>{font.family}</li>
      </ul>
    )
  })
}

<FormControl
    style={inputFieldStyle}
    componentClass="select"
    placeholder="select" >
  {setTimeout(this.renderFonts, 100)}
</FormControl>

3 个答案:

答案 0 :(得分:0)

你可以尝试这样的事情:

//after `render()`
const data = this.state.googleFonts.data.items

return (
  <FormControl
   style={inputFieldStyle}
   componentClass="select"
   placeholder="select"
  >
    {data && data.map((font, index) => 
        <option>{font.family}</option>
     )}
  </FormControl>

我相信这就是React-Bootstrap期望它被编写的方式,并且它的代码少了一点。使用逻辑&&运算符可以在状态加载后填充下拉列表。

答案 1 :(得分:0)

这里有一些问题。

首先:{setTimeout(this.renderFonts, 100)}返回timeoutID是一个正整数值,它标识通过调用setTimeout()创建的计时器,因此尽管执行了renderFonts,但是从它返回的任何内容都不会被呈现< / p>

第二:在渲染之后调用componentDidMount并且你在componentDidMount中有你的API请求,因此使用setTimeout延迟要渲染的值是一个可怕的想法,因为你永远无法确定何时会得到来自API的响应,对于慢速网络,它可能需要很长时间,因此即使在超过100毫秒后,您可能仍然没有数据,因此this.state.googleFonts.data.items可能仍未定义或响应可能在10毫秒,在这种情况下,您不必要地延迟渲染。

A better way to solve this is to have provide a check for the presence of data.

你可以这样做

constructor() {
  super();
  this.state = {
  };

componentDidMount() {
  let URL = is the url with my api key (it works)
  axios.get(URL)
  .then((data) => {
      console.log("data" + data);
      this.setState({
        googleFonts: data
      })
  })
  .catch((err) => {
    console.log(err);
    this.setState({
      errors: err
    })
  })
}

renderFonts() {
  let data = this.state.googleFonts? this.state.googleFonts.data.items: [];
  return data.map((font, index) => {
    console.log(font.family);
    return (
     <ul>
       <li>{font.family}</li>
      </ul>
    )
  })
}

<FormControl
    style={inputFieldStyle}
    componentClass="select"
    placeholder="select" >
  {this.renderFonts()}
</FormControl>

答案 2 :(得分:0)

这应该对你有所帮助。它更多地与您构建代码和回调的方式有关。看一下这个样本 -

import React from 'react';
import axios from 'axios'

class Hello extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: 'there',
      title: null
    };
  }

  componentWillMount() {
    let URL = 'https://fakerestapi.azurewebsites.net/api/Books'
    axios({
      method: 'get',
      url: URL,
      responseType: 'json'
    })
      .then((data) => {
        console.log(data.data);
        this.setState({
          title: data.data[0].Title
        })
      })
      .catch((err) => {
        console.log(err);
        this.setState({
          errors: err
        })
      })
  }

  render() {
    return (
      <div className="component-app">
        <h1>Hello {this.state.name}! {'\u2728'}</h1>
        <h2>{this.state.title}</h2>
      </div>
    );
  }
}

export default Hello;

我在这里编码了。看看

Edit l2j0rx5qxm

您可以使用componentDidMount代替componentWillMount。你也会在控制台中看到错误,你的代码就像React - setState() on unmounted component一样。如果你解决了这个问题,那么你应该可以使代码正常工作。