1

I'm working on something that allows users to type in a username and display all the github repos for that user in a separate react component inside a repolist component.

I can get the JSON data for all the repos but I can't iterate through the object to display a card for each repo, I don't know how to reference the data nested inside the object.

I should note that testData was originally filled with test data that I could only get working as a single dimensional array, rather than an object.

App.js:


    import React from 'react';
    import { CardList } from './Components/CardList.js';
    import { testData } from './Components/Card.js'
    import { Form } from './Components/Form.js'; 
    import './App.css';

    class App extends React.Component {

      state = {
        profiles: testData,
      };
      addNewSearch = (searchData) => {
        this.setState(prevState => ({
          profiles: [...prevState.profiles, searchData],
        }))
      };

      render() {
        return (
          <div className="App">
            <header className="App-header">
            <div>{this.props.title}</div>
              <div className=" search-box" style={{textAlign: 'center'}}>
                <Form onSubmit={this.addNewSearch}/>
              </div>
              <div className="bgbox rounded">

                <div className="cardbox">
                  <CardList profiles={this.state.profiles} />
                </div>
              </div>
            </header>
          </div>
        );
      }
    }

    export default App

Form.js


    import React from 'react';
    import axios from 'axios';

    export class Form extends React.Component {
        state = { userName: '' };
        handleSubmit = async (event) => {
            event.preventDefault();
            const resp = await
            axios.get(`https://api.github.com/users/${this.state.userName}/repos?per_page=250`)
            this.props.onSubmit(
                resp.data
            );

        };
        render() {
            return (
                <form onSubmit={this.handleSubmit}>
                    <div className="btn-group">
                        <input type="text" value={this.state.userName} className="form-control" placeholder="GitHub User" onChange={event => this.setState({userName: event.target.value })}></input>
                        <button className="btn btn-dark">Go!</button>
                    </div>
                </form>
            )
        }
    }

Card.js


    import React from 'react';

    export const testData = [];


    export class Card extends React.Component {
        render() {
            const repo = this.props;
            return (
                <div className="card border-secondary mb-3" style={{ width: '20rem', fontSize: '12px'}}>
                    <h5 className="card-header">{repo.name}</h5>
                    <div className="card-body text-secondary">
                        <p className="card-text">{repo.name}</p>
                    </div>
                </div>
            );
        }
    }


CardList.js


    import React from 'react';
    import { Card } from './Card.js'

    export const CardList = (props) => (
        <div>
            {props.profiles.map(profile => <Card key={profile.id} {...profile} />)}
        </div>
    );

Edit: screenshot of what it currently looks like image of card rendered

1 Answer 1

1

First you need to see that is the result from the request you are making.

[
  {
    "id": 123456,
    "name": "bla-bla-repo",
    ...
  },
  ...
]

On each request you get an array of repos of a user.

You are storing a all repos of some user, so you have an array of user's repos. (Array of array)

When doing profiles.map(profile => ...), profile is an array of repos. You can't access profile.id.

What you can do a .map inside another .map.

{props.profiles.map(profile => profile.map(repo => <Card key={repo.id} repo={repo} />))}

This will List all repos of all users.


If this isn't what you want to do, and you want to display all the repos of only one user, you need to pass to CardList, only one profile.

<CardList profiles={this.state.profiles[indexOfTheProfileYouWantToDisplay]} />
Sign up to request clarification or add additional context in comments.

2 Comments

Hi, this is perfect. i added your last line to my App.js and change it so that it would only render one cardlist. I added one line of dummy data so it would have something to display or it would error. When i searched for a username it replaced the dummy data with the list of repos! May I ask, do you know how to stop it from throwing an error when there is no [0] in the array?
@HollowA you should do some checking like this.state.profiles && this.state.profiles[0], because profiles can be null or undefined. You should do this checking every time you use .map, also doing it in {props.profiles && props.profiles.map(...)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.