Reactjs 无法通过从外部API获取数据来更新状态

Reactjs 无法通过从外部API获取数据来更新状态,reactjs,react-router,Reactjs,React Router,我正在制作一个小应用程序,其中我从外部github API获取数据并更新状态,但我得到一个错误,该错误表示无法读取null的属性。我创建了两个文件,其中api.js从外部github api获取数据,如代码所示。和Results.js文件相应地更新状态。下面我附上了错误的截图。有人能帮我找出代码中的问题吗 代码:: api.js import axios from 'axios'; var id = "YOUR_CLIENT_ID"; var sec = "YOUR_SECRET_ID"; v

我正在制作一个小应用程序,其中我从外部github API获取数据并更新状态,但我得到一个错误,该错误表示无法读取null的属性。我创建了两个文件,其中api.js从外部github api获取数据,如代码所示。和Results.js文件相应地更新状态。下面我附上了错误的截图。有人能帮我找出代码中的问题吗

代码::

api.js

import axios from 'axios';

var id = "YOUR_CLIENT_ID";
var sec = "YOUR_SECRET_ID";
var params = "?client_id=" + id + "&client_secret=" + sec;

function getProfile (username) {
  return axios.get('https://api.github.com/users/' + username + params)
    .then(function (user) {
      return user.data;
    });
}

function getRepos (username) {
  return axios.get('https://api.github.com/users/' + username + '/repos' + params + '&per_page=100');
}

function getStarCount (repos) {
  return repos.data.reduce(function (count, repo) {
    return count + repo.stargazers_count
  }, 0);
}

function calculateScore (profile, repos) {
  var followers = profile.followers;
  var totalStars = getStarCount(repos);

  return (followers * 3) + totalStars;
}

function handleError (error) {
  console.warn(error);
  return null;
}

function getUserData (player) {
  return axios.all([
    getProfile(player),
    getRepos(player)
  ]).then(function (data) {
    var profile = data[0];
    var repos = data[1];

    return {
      profile: profile,
      score: calculateScore(profile, repos)
    }
  });
}

function sortPlayers (players) {
  return players.sort(function (a,b) {
    return b.score - a.score;
  });
}

export default {
  battle: function (players) {
    return axios.all(players.map(getUserData))
      .then(sortPlayers)
      .catch(handleError);
  },

  fetchPopularRepos: function (language) {
    var encodedURI = window.encodeURI('https://api.github.com/search/repositories?q=stars:>1+language:'+ language + '&sort=stars&order=desc&type=Repositories');

    return axios.get(encodedURI)
      .then(function (response) {
        return response.data.items;
      });
  }
};
Results.js

import React from 'react';
import queryString from 'query-string';
import api from '../utils/api';
import { Link } from 'react-router-dom';
import PropTypes from 'prop-types';

function Player (props) {
   return (
      <div>
         <h1 className='header'> {props.label} </h1>
         <h3 style={{textAlign: 'center'}}> Score: {props.score} </h3>
      </div>
   )
}

Player.propTypes = {
   label: PropTypes.string.isRequired,
   score: PropTypes.number.isRequired,
   profile: PropTypes.object.isRequired
}

class Results extends React.Component {
   constructor(props) {
      super(props);

      this.state = {
         winner: null,
         loser: null,
         error: null,
         loading: true
      }
   }

   componentDidMount() {
    var players = queryString.parse(this.props.location.search);

    api.battle([
      players.playerOneName,
      players.playerTwoName
    ]).then(function (players){
      if (players === null) {
        return this.setState(function () {
          return {
            error: 'Looks like there was an error. Check that both users exist on Github.',
            loading: false,
          }
        });
      }

      this.setState(function () {
        return {
          error: null,
          winner: players[0],
          loser: players[1],
          loading: false,
        }
      });
    }.bind(this));
   }

   render () {
      var error = this.state.error;
      var winner = this.state.winner;
      var loser = this.state.loser;
      var loading = this.state.loading;

      if(loading === true){
         <p> Loading !! </p>
      }

      if (error) {
        return (
          <div>
            <p>{error}</p>
            <Link to='/battle'>Reset</Link>
          </div>
        )
      }

      return (
        <div className='row'>
          <Player
            label='Winner'
            score={winner.score}
            profile={winner.profile}
          />
          <Player
            label='Loser'
            score={loser.score}
            profile={loser.profile}
          />
        </div>
      )
    }
}

export default Results;
从“React”导入React;
从“查询字符串”导入查询字符串;
从“../utils/api”导入api;
从'react router dom'导入{Link};
从“道具类型”导入道具类型;
功能播放器(道具){
返回(
{props.label}
分数:{props.Score}
)
}
Player.propTypes={
标签:PropTypes.string.isRequired,
分数:PropTypes.number.isRequired,
配置文件:PropTypes.object.isRequired
}
类结果扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
获胜者:空,
失败者:空,
错误:null,
加载:正确
}
}
componentDidMount(){
var players=queryString.parse(this.props.location.search);
api.battle([
players.playername,
玩家名称
]).然后(功能(玩家){
如果(玩家===null){
返回此.setState(函数(){
返回{
错误:“看起来有错误。请检查Github上是否存在两个用户。”,
加载:false,
}
});
}
this.setState(函数(){
返回{
错误:null,
获胜者:玩家[0],
输家:玩家[1],
加载:false,
}
});
}.约束(这个);
}
渲染(){
var error=this.state.error;
var winner=this.state.winner;
var loser=this.state.loser;
var loading=this.state.loading;
如果(加载===true){
正在加载

} 如果(错误){ 返回( {错误}

重置 ) } 返回( ) } } 导出默认结果;
错误:


此.state.winner
在提取完成之前为空,这将触发错误

最初将其设置为
{}
,以便尝试访问其属性不会导致错误:

this.state = {
  winner: {},
  // insert other states
}

非常感谢@riwu。我是否还需要设置**var error:{}**?不,您将其呈现为字符串
{error}

。您需要将
this.state.loser
设置为
{}
,因为您正在访问
this.state.loser.score