对地图功能中的每个项目进行Ajax调用

时间:2018-11-22 22:59:38

标签: javascript reactjs

在以下情况下,我需要在数组上映射并在屏幕上显示时向数组的每个项目的端点发出ajax请求。

const items = [
    {
        id: 1,
        name: "test"
    },
    {
        id: 2,
        name: "test2"
    }
]

在我的render()方法中:

render(){

    return (
        items.map((item) => {
            <div>{item.name}</div>

            // function that returns a promise
            // the endpoint requires the item's id
            this.apiCall(item.id).then((returnedValue) => {
                return <div>{returnedValue}</div>
            });
        })
    );
}

但是运行它会引发此错误:

Uncaught (in promise) Error: Minified React error #31; Objects are not valid as a React child (found: [object Promise]).

3 个答案:

答案 0 :(得分:0)

我们可以像这样使用Promise.all()

return (
    Promise.all(items.map((item) => {
        <div>{item.name}</div>
        // function that returns a promise
        // the endpoint requires the item's id
        this.apiCall(item.id).then((returnedValue) => {
            return <div>{returnedValue}</div>
        });
    })
);

答案 1 :(得分:0)

您不能在render方法中执行异步操作,但可以将Api调用封装在子组件中(改为渲染),然后可以在子组件逻辑中处理该调用,大致如下:

constructor(props) {
  apiCall(props.id).then((value) => { this.setState({value}) });

  this.state = {
      value: ''
  }
}

render() {
    return (<div>{this.state.value}</div>);
}

答案 2 :(得分:0)

您需要从render方法同步返回JSX,因此最好将API数据保存在componentDidMount中,并在请求完成后将其设置为组件状态。

示例

class App extends React.Component {
  state = { items: [] };

  componentDidMount() {
    const items = [
      {
        id: 1,
        name: "test"
      },
      {
        id: 2,
        name: "test2"
      }
    ];

    Promise.all(
      items.map(item =>
        this.apiCall(item.id).then(returnedValue => {
          item.returnedValue = returnedValue;
          return item;
        })
      )
    ).then(items => {
      this.setState({ items });
    });
  }

  apiCall = id => {
    return new Promise(resolve =>
      setTimeout(() => resolve(Math.random()), 1000)
    );
  };

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

    return (
      <div>
        {items.map(item => (
          <div key={item.id}>
            <div>{item.name}</div>
            <div>{item.returnedValue}</div>
          </div>
        ))}
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>