Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/471.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 无法在componentDidMount内设置状态_Javascript_Reactjs_Google Maps Api 3_Fetch - Fatal编程技术网

Javascript 无法在componentDidMount内设置状态

Javascript 无法在componentDidMount内设置状态,javascript,reactjs,google-maps-api-3,fetch,Javascript,Reactjs,Google Maps Api 3,Fetch,我从Google place search API中获取一些数据,然后使用其位置ID获取特定位置的所有详细信息。place search API返回一个包含20条记录的数组,首先,我循环一个数组,获取每个位置的place_id,然后再次获取循环中位置的详细信息,并将其放入数组中,然后将状态设置为该数组。但是当我在render函数中执行{this.state.rows}时,它会给我一个空数组。 下面是我的代码: import React, { Component } from 'react'; i

我从Google place search API中获取一些数据,然后使用其位置ID获取特定位置的所有详细信息。place search API返回一个包含20条记录的数组,首先,我循环一个数组,获取每个位置的place_id,然后再次获取循环中位置的详细信息,并将其放入数组中,然后将状态设置为该数组。但是当我在render函数中执行
{this.state.rows}
时,它会给我一个空数组。 下面是我的代码:

import React, { Component } from 'react';
import {
    Table,
    ProgressBar
} 
from 'react-bootstrap';

class Display extends Component {
        constructor(props) {
            super(props);
            this.state={
                rows: []
            }
        }


    componentDidMount(){
        var records = this.props.googleData;
        const API = this.props.api;
        const placeURI = this.props.placeURI;
        var rows = [];
        for (let p_id of records.results) {
            let dataURI = `${placeURI}${p_id.place_id}${API}`;
            let proxyUrl = 'https://cors-anywhere.herokuapp.com/',
                targetUrl = dataURI
            fetch(proxyUrl + targetUrl)
            .then((res) => res.json())
            .then((data) => {
                let jsonData = JSON.parse(JSON.stringify(data));
                //console.log(jsonData);
                rows.push(jsonData.result);
            })
            .catch((e) => console.log(`Error! ${e.message}`));
        }
        this.setState({
            rows:rows
        });
    };

    render() {
        console.log(this.state.rows); //this line is printing two arrays on console one is empty and the other is populated with values.
        return (
            <div>
                <ProgressBar now={45} />
                <Table striped bordered condensed hover responsive>
                  <thead>
                    <tr>
                      <th>#</th>
                      <th>Name</th>
                      <th>Full Address</th>
                      <th>Phone Number</th>
                      <th>International P.no</th>
                      <th>Website</th>
                      <th>Rating</th>
                    </tr>
                  </thead>
                  <tbody>
                    {this.state.rows.map(( listValue, index ) => {
                      return (
                        <tr key={index}>
                          <td>{listValue.name}</td>
                          <td>{listValue.formatted_address}</td>
                          <td>{listValue.name}</td>
                          <td>{listValue.name}</td>
                          <td>{listValue.name}</td>
                          <td>{listValue.name}</td>
                          <td>{listValue.name}</td>
                        </tr>
                      );
                    })}
                  </tbody>
                </Table>
                {this.state.rows+"hell"} // this line is not returning my current state
            </div>
        );
    }

}
export default Display;
import React,{Component}来自'React';
进口{
桌子
进度条
} 
来自“反应引导”;
类显示扩展了组件{
建造师(道具){
超级(道具);
这个州={
行:[]
}
}
componentDidMount(){
var records=this.props.googleData;
const API=this.props.API;
const placeURI=this.props.placeURI;
var行=[];
for(让p_id记录。结果){
让dataURI=`${placeURI}${p_id.place_id}${API}`;
让proxyUrl为https://cors-anywhere.herokuapp.com/',
targetUrl=dataURI
获取(代理URL+目标URL)
.然后((res)=>res.json())
。然后((数据)=>{
让jsonData=JSON.parse(JSON.stringify(data));
//console.log(jsonData);
rows.push(jsonData.result);
})
.catch((e)=>console.log(`Error!${e.message}`));
}
这是我的国家({
行:行
});
};
render(){
console.log(this.state.rows);//此行在控制台上打印两个数组,一个为空,另一个为值填充。
返回(
#
名称
全称
电话号码
国际邮政编码
网站
评级
{this.state.rows.map((listValue,index)=>{
返回(
{listValue.name}
{listValue.formatted_address}
{listValue.name}
{listValue.name}
{listValue.name}
{listValue.name}
{listValue.name}
);
})}
{this.state.rows+“hell”}//此行没有返回我的当前状态
);
}
}
导出默认显示;

请考虑我在代码中添加的注释以了解行为。请帮我解决这个问题。

Fetch是异步的,因此在执行
setState
之后,结果将被推送到
行中,并且不会更新任何内容。要获得所需的行为,请删除
var rows
this.setState({rows:rows})
,并将
rows.push(jsonData.result)
替换为
this.setState(prevState=>({rows:[…prevState.rows,jsonData.result]}))

请记住,行的顺序将由提取请求完成的顺序决定,因此如果要保证顺序,应创建
fetch
承诺列表,并使用
Promise.all
设置状态。您也可以使用async/await for循环,但这意味着每次提取都将等待上一次提取完成,从而消除并行性并影响性能

更新:简而言之,用以下内容替换
componentDidMount

componentDidMount(){
    var records = this.props.googleData;
    const API = this.props.api;
    const placeURI = this.props.placeURI;

    for (let p_id of records.results) {
        const dataURI = `${placeURI}${p_id.place_id}${API}`;
        const proxyUrl = 'https://cors-anywhere.herokuapp.com/',
            targetUrl = dataURI
        fetch(proxyUrl + targetUrl)
        .then((res) => res.json())
        .then((data) => {
            const jsonData = JSON.parse(JSON.stringify(data));
            //console.log(jsonData);
            this.setState(prevState => ({rows: [...prevState.rows, jsonData.result]}))
        })
        .catch((e) => console.log(`Error! ${e.message}`));
    }
};
更新2:这里有一些(未经测试的)代码带有
Promise.all
,它保留了行顺序:

componentDidMount(){
  const records = this.props.googleData;
  const API = this.props.api;
  const placeURI = this.props.placeURI;
  const proxyUrl = 'https://cors-anywhere.herokuapp.com/'; // move this outside of component

  const rowFetches = records.results.map((p_id) =>
    fetch(`${proxyUrl}${placeURI}${p_id.place_id}${API}`)
    .then((res) => res.json())
  );
  const rows = Promise.all(rowFetches)
  .then((rows) => this.setState({rows}))
  .catch((e) => console.log(`Error! ${e.message}`));
}

它无法工作,因为获取是异步的。(例如:行
rows.push(jsonData.result);
实际上发生在执行
this.setState({rows:rows});
!)

我建议您创建一个新函数来创建数组并将其设置为状态。为了更好的可读性,您可以使用async/await语法,下面是我的做法:

async loadArray(results){
  const API = this.props.api;
  const placeURI = this.props.placeURI;
  let rows = [];
  for (let p_id of results) {
        let dataURI = `${placeURI}${p_id.place_id}${API}`;
        let proxyUrl = 'https://cors-anywhere.herokuapp.com/',
            targetUrl = dataURI
        let res = await fetch(proxyUrl + targetUrl);
        res = await res.json();
        let jsonData = JSON.parse(JSON.stringfy(res))
        rows.push(jsonData.result)
    }
    this.setState({
        rows:rows
    });
}
componentDidMount(){
    const records = this.props.googleData;
    this.loadArray(records.results)
}

Async/await for循环非常优雅,但在这里它们消除了并行性,因为每次获取都需要服务器响应,然后才能发送下一个。你说得对。这样做只保留一个设置状态。我们可以说我使代码工作,但不是最优化的。你的答案很理想,但我又犯了一个错误
this.loadArray不是
componentDidMount
内部的函数,请详细说明。我是React的初学者。没有得到你的答案。这远远超出了我的水平,非常感谢。我真的很感谢你。我真的很感激。我在这件事上浪费了两天时间。再次非常感谢你