无法读取未定义反应的属性“键”

时间:2020-09-07 00:06:41

标签: reactjs api github axios

Home.js组件

import React, { Component } from 'react';
import axios from 'axios';

import styles from './home.module.css';
import TurnArrow from '../../assets/images/turn.svg';
import LoadingGif from '../../assets/images/loading.gif';

import SearchBox from '../SearchBox/SearchBox';
import RepoItem from '../RepoItem/RepoItem';

class Home extends Component {
    constructor(props) {
        super(props)
        
        this.state = {
            repos: [],
            inputValue: "",
            isEmptySearch: false,
            isLoading: false,
            per_page: 100,
            limit: 10,
            total_count: null,
            showMore: true,
            index: 10,
            dataLoaded: false,
            reposLength: null
        }

        this.myRef = React.createRef();

        this.updateInputValue = this.updateInputValue.bind(this);
        this.fetchRepos = this.fetchRepos.bind(this);
        this.handleClick = this.handleClick.bind(this);
        this.handleKeyPress = this.handleKeyPress.bind(this);
    }

    scrollToMyRef() {
        window.scrollTo(0, this.myRef.current.offsetTop);
    }

    updateInputValue(e) {
        this.setState({
            inputValue: e.target.value
        });
    }

    fetchRepos() {
        if(this.state.inputValue.trim() === "" || this.state.inputValue.trim() === null) {
            return this.setState({ isEmptySearch: true});
        } 
        
        this.setState({ 
            isEmptySearch: false,
            isLoading: true
        });

        axios.get(`https://api.github.com/search/repositories?q=${this.state.inputValue}&per_page=100`)
            .then(response => {
                this.setState({ 
                    total_count: response.data.total_count, 
                    repos: response.data.items,
                    isLoading: false,
                    dataLoaded: true,
                    reposLength: response.data.items.length
                 })

                 return this.scrollToMyRef();
                
            })
            .catch(err => console.log(err));
    }

    handleClick() {
        this.fetchRepos();
    }

    handleKeyPress(e) {
        if(e.key === "Enter") {
            this.fetchRepos();
        }

        return
    }

    render() {
        let { repos, isEmptySearch, total_count, isLoading } = this.state;
        return (
            <>
            <header className={styles.hero}>
                <div className="container">
                    <div className={styles.innerHero}>
                        <div>
                            <h1>Welcome to GIT M<span>EƎ</span>T</h1>
                            <p>Discover millions of github repositories <br></br>right here, right now.</p>
                            <p>Start by using the search box on the right.</p>
                        </div>
                        <div className={styles.searchBox}>
                            <SearchBox>
                                <img src={TurnArrow} alt="arrow pointing to search button" />
                                <h1>Search Repos</h1>
                                <input onKeyPress={this.handleKeyPress} onChange={this.updateInputValue} type="text" name="search" id="search" placeholder="E.g. 'ultra amazing html h1 tag...'" autoComplete="off" required />
                                <button disabled={ isLoading ? true : false } onClick={this.handleClick}>{ isLoading ? <img src={LoadingGif} alt="loading..." /> : "Search" }</button>
                                { isEmptySearch ? <p className={styles.errorMessage}>Please enter something first!</p> : "" }
                            </SearchBox>
                        </div>
                    </div>
                </div>
            </header>
            <main>
                {this.state.dataLoaded ? <RepoItem ref={this.myRef} total_count={total_count} repos={repos}/> : "" }
                <button className={styles.loadMore}>Load More</button> 
                
            </main>
            </>
        );
    }
}

export default Home;

RepoList组件

import React, { useState, useEffect } from 'react'

import styles from './repo_item.module.css';

import Footer from '../Footer/Footer';

const RepoList = React.forwardRef((props, ref) => {

    const [repos, setRepos] = useState([props.repos]);

    useEffect(() => {
        setRepos(props.repos);
    }, [props.repos]);

    return (
        <>
       <div className="container">
           <div className={styles.infoWrap}>
               <h2>Results</h2>
                <p>Found {props.total_count} results</p>
           </div>
           <div ref={ref} className={styles.repoWrap}>
                {repos.length > 0 ? repos.map((item,index) => {
                    console.log(item);
                    return (
                        <div key={index} className={styles.repoItem}>
                            <div className={styles.userProfile}>
                                
                            </div>
                            { item.name && item.name.length > 20 ? item.name.substring(0,20) + "..." : item.name }
                            { item.license.key }
                        </div>
                    );
                }) : ""}
           </div>
       </div>
       <Footer />
       </>
    );
})

export default RepoList;

为什么... item.license.key不起作用,但item.name起作用.........帮助。 我想弄清楚Home和repo组件之间的连接,但是看不到我自己的错误。那就是为什么我在这里发布它,也许有人会更快地注意到问题。

预先感谢您,我尝试检查项目及其内容,但每次都会遇到相同的错误。

1 个答案:

答案 0 :(得分:0)

发现很多问题不在代码中之后,就是从API获取的数据,例如https://api.github.com/search/repositories?q=bootstrap&per_page=100

license属性为null,因此您遇到了问题。

检查空条件 {item.license && item.license.key}

API调用响应:

{
   "total_count":276072,
   "incomplete_results":false,
   "items":[
      {
         "id":2126244,
         "node_id":"MDEwOlJlcG9zaXRvcnkyMTI2MjQ0",
         "name":"bootstrap",
         .....
         "license":{
            "key":"mit",
            "name":"MIT License",
            "spdx_id":"MIT",
            "url":"https://api.github.com/licenses/mit",
            "node_id":"MDc6TGljZW5zZTEz"
         },
        ......
      },
      {
         "id":5689093,
         "node_id":"MDEwOlJlcG9zaXRvcnk1Njg5MDkz",
         "name":"android-bootstrap",
         .....
         "license":null,
         .....
      }
   ]
}