Javascript 我正在从API请求数据。目前,我以对象数组的形式获取数据,但我';我无法在浏览器上渲染输出

Javascript 我正在从API请求数据。目前,我以对象数组的形式获取数据,但我';我无法在浏览器上渲染输出,javascript,reactjs,Javascript,Reactjs,下面是我为从API获取匹配细节而编写的代码。我正在获取数据并将其转换为JSON格式。我可以将数据添加到匹配数组中,但无法将其渲染到屏幕上 import React, { Component } from 'react'; import './App.css'; import Person from './Person/Person'; class App extends Component { state = { match: [ { id: '12', stat: '

下面是我为从API获取匹配细节而编写的代码。我正在获取数据并将其转换为JSON格式。我可以将数据添加到匹配数组中,但无法将其渲染到屏幕上

import React, { Component } from 'react';
import './App.css';
import Person from './Person/Person';

class App extends Component {
  state = {
    match: [
      { id: '12', stat: 'he', score: 's',description:'sds'},
      { id: '', stat: '', score: '',description:''},
      { id: '', stat: '', score: '',description:''},
      { id: '', stat: '', score: '',description:''},
      { id: '', stat: '', score: '',description:''}

    ],
    otherState: 'some other value'
  }

  GetMatchNumber = async () => {
    const responseofmatchno = await fetch(`https://cricapi.com/api/matches?apikey={API_KEY}`);
    const dataofmatchno = await responseofmatchno.json(); 
    const length = dataofmatchno.matches.length;
    var actual_length=0;
    var p=0;
    let true_value = "true";
    while(++p < length)
    {
      if((dataofmatchno.matches[p].matchStarted.valueOf()) === (dataofmatchno.matches[0].matchStarted))
      {
        actual_length = actual_length + 1;
      }
    }
    let i = 0;
    let j=0;
    while(++i < 4)
    {
      j=dataofmatchno.matches[i].unique_id;
      this.state.match[i].id=(dataofmatchno.matches[i].unique_id);
      console.log(this.state.match[i].id);
      const responseofmatchdetails = await fetch(`http://cricapi.com/api/cricketScore?unique_id=${j}&apikey={API_KEY}`);
      const dataofmatch = await responseofmatchdetails.json();
      this.state.match[i].stat=(dataofmatch.stat);
      console.log(this.state.match[i].stat);
      this.state.match[i].score=(dataofmatch.score);
      console.log(this.state.match[i].score);
      this.state.match[i].description=(dataofmatch.description);
      console.log(this.state.match[i].description);
    }
  }
  render () {
    console.log(this.state.match[0].id);
    return (
      <div className="App">
        <h1>Hi, I'm a React App</h1>
        <p>This is really working!</p>
        <p>{this.state.match[0].id}</p>
        <button onClick= {this.GetMatchNumber()}></button>
        <Person 
          id={this.state.match[0].id} 
          stat={this.state.match[0].stat} />
        <Person 
          id={this.state.match[1].id} 
          stat={this.state.match[1].stat} />
        <Person 
          id={this.state.match[2].id} 
          stat={this.state.match[2].stat} />
      </div>
    );
  }
}

尝试componentDidMount中的API调用,因为它将被调用一次(仅第一次渲染),然后使用此.setState更新状态。

渲染函数应该是一个纯函数,返回要显示的结果,不应该有任何副作用,例如获取数据。相反,使用一个react组件生命周期函数(或回调)来发出副作用和/或更新状态。你也在直接改变状态

首先计算要将状态设置为/使用的整个对象,并使用新状态对象调用
setState
。在这种情况下,您可以将所有获取请求排队,并使用
Promise.all
“批量”处理它们。我还建议您在所有异步处理过程中使用try/catch,以防出现错误,这样您就可以处理它,并让您的应用程序保持良好的运行状态

另外,确保正确设置按钮的
onClick
回调

import React, { Component } from 'react';
import './App.css';
import Person from './Person/Person';

class App extends Component {
  state = {
    match: [
      { id: '12', stat: 'he', score: 's',description:'sds'},
      { id: '', stat: '', score: '',description:''},
      { id: '', stat: '', score: '',description:''},
      { id: '', stat: '', score: '',description:''},
      { id: '', stat: '', score: '',description:''}

    ],
    otherState: 'some other value'
  }

  getMatchNumber = async () => {
    const responseOfmatchNo = await fetch(`https://cricapi.com/api/matches?apikey={API_KEY}`);
    const dataOfMatchNo = await responseOfmatchNo.json();

    const resolvedFetchedJSON = await Promise.all(
      // map data objects to fetch requests, returns json data
      dataOfMatchNo.matches.map(request => {
        return fetch(`http://cricapi.com/api/cricketScore?unique_id=${request.unique_id}&apikey={API_KEY}`)
        .then(response => response.json());
      })
    );

    // at this point I think you have the array of JSON data you were copying previously
    this.setState({ match: resolvedFetchedJSON });

    /**
     * NOTE: if you want to keep existing matches in state, i.e. merge in new data then
     * this.setState(prevState => ({ match: [...prevState.match, ...resolvedFetchedJSON]}));
     */
  }

  render () {
    console.log(this.state.match[0].id);
    return (
      <div className="App">
        <h1>Hi, I'm a React App</h1>
        <p>This is really working!</p>
        <p>{this.state.match[0].id}</p>
        {/* <button onClick= {this.GetMatchNumber()}></button> */}
        {
          /**
           * Don't invoke onClick callback immediately, either
           *  - define in-line callback
           *    <button onClick= {() => this.GetMatchNumber()}></button>
           *  - or set callback as your function, notice no parans on function 
           *    <button onClick= {this.GetMatchNumber}></button>
           */
        }
        <button onClick= {this.GetMatchNumber}></button>
        <Person 
          id={this.state.match[0].id} 
          stat={this.state.match[0].stat} />
        <Person 
          id={this.state.match[1].id} 
          stat={this.state.match[1].stat} />
        <Person 
          id={this.state.match[2].id} 
          stat={this.state.match[2].stat} />
      </div>
    );
  }
}
import React,{Component}来自'React';
导入“/App.css”;
从“./人/人”导入人;
类应用程序扩展组件{
状态={
匹配:[
{id:'12',stat:'he',score:'s',description:'sds'},
{id:'',stat:'',score:'',description:'},
{id:'',stat:'',score:'',description:'},
{id:'',stat:'',score:'',description:'},
{id:'',stat:'',score:'',description:''}
],
otherState:“其他值”
}
getMatchNumber=async()=>{
const responseOfmatchNo=等待获取(`https://cricapi.com/api/matches?apikey={API_KEY}`);
const dataOfMatchNo=wait responseOfmatchNo.json();
const resolvedFetchedJSON=wait Promise.all(
//映射数据对象以获取请求,返回json数据
dataOfMatchNo.matches.map(请求=>{
回传(`http://cricapi.com/api/cricketScore?unique_id=${request.unique\u id}&apikey={API\u KEY}`)
.then(response=>response.json());
})
);
//此时,我认为您已经拥有了之前复制的JSON数据数组
this.setState({match:resolvedFetchedJSON});
/**
*注意:如果您希望保持现有匹配的状态,即合并到新数据中,则
*this.setState(prevState=>({match:[…prevState.match,…resolvedFetchedJSON]});
*/
}
渲染(){
console.log(this.state.match[0].id);
返回(
嗨,我是React应用程序
这真的很有效

{this.state.match[0].id}

{/* */} { /** *也不要立即调用onClick回调 *-定义在线回调 *this.GetMatchNumber()}> *-或将callback设置为函数,请注意函数上没有parans * */ } ); } }
如果您正在直接改变状态,则不应这样做。这就是为什么你的状态值没有显示在屏幕上。相反,您需要使用
this.setState
函数更新您的状态。另外,您不应该更新循环中的状态,因为这意味着您的组件将重新呈现每个循环迭代,这可能会导致性能问题TypeError:无法读取未定义的属性“1”。如果不在渲染函数中执行副作用,请使用生命周期函数,如
componentDidMount
。当你的意思是
true
时,不要使用
“true”
。也不应该在一个循环中生成一组异步获取请求,而是将它们排队到一个数组中,并
承诺。所有
请求在全部解析时批量处理所有请求。然后您应该能够合并状态更新。非常感谢。它工作得很好,但复制内容只需要稍多的时间。有没有办法减少延迟?在上面的代码中,我只有5个匹配类型的对象。你能不能建议一个合适的方法,根据现在正在进行的比赛的数量,我将有比赛类型的对象。对于延迟,你可能做不了什么,我假设你指的是网络延迟和服务器响应时间。我不太明白你的第二个问题。你能再解释一点吗?有没有比我在这里做的更好的方法来声明对象数组(这里我有一个“匹配”对象的数组,它具有stat、description等属性)?动态的东西,它会根据比赛的数量创建对象?假设有10个匹配正在进行,而数组对象的大小(这里的匹配)应该是10,我不必首先声明数组的大小(这里我的数组大小是5)。
import React, { Component } from 'react';
import './App.css';
import Person from './Person/Person';

class App extends Component {
  state = {
    match: [
      { id: '12', stat: 'he', score: 's',description:'sds'},
      { id: '', stat: '', score: '',description:''},
      { id: '', stat: '', score: '',description:''},
      { id: '', stat: '', score: '',description:''},
      { id: '', stat: '', score: '',description:''}

    ],
    otherState: 'some other value'
  }

  getMatchNumber = async () => {
    const responseOfmatchNo = await fetch(`https://cricapi.com/api/matches?apikey={API_KEY}`);
    const dataOfMatchNo = await responseOfmatchNo.json();

    const resolvedFetchedJSON = await Promise.all(
      // map data objects to fetch requests, returns json data
      dataOfMatchNo.matches.map(request => {
        return fetch(`http://cricapi.com/api/cricketScore?unique_id=${request.unique_id}&apikey={API_KEY}`)
        .then(response => response.json());
      })
    );

    // at this point I think you have the array of JSON data you were copying previously
    this.setState({ match: resolvedFetchedJSON });

    /**
     * NOTE: if you want to keep existing matches in state, i.e. merge in new data then
     * this.setState(prevState => ({ match: [...prevState.match, ...resolvedFetchedJSON]}));
     */
  }

  render () {
    console.log(this.state.match[0].id);
    return (
      <div className="App">
        <h1>Hi, I'm a React App</h1>
        <p>This is really working!</p>
        <p>{this.state.match[0].id}</p>
        {/* <button onClick= {this.GetMatchNumber()}></button> */}
        {
          /**
           * Don't invoke onClick callback immediately, either
           *  - define in-line callback
           *    <button onClick= {() => this.GetMatchNumber()}></button>
           *  - or set callback as your function, notice no parans on function 
           *    <button onClick= {this.GetMatchNumber}></button>
           */
        }
        <button onClick= {this.GetMatchNumber}></button>
        <Person 
          id={this.state.match[0].id} 
          stat={this.state.match[0].stat} />
        <Person 
          id={this.state.match[1].id} 
          stat={this.state.match[1].stat} />
        <Person 
          id={this.state.match[2].id} 
          stat={this.state.match[2].stat} />
      </div>
    );
  }
}