Loading an array of objects from a JSON and storing in an interactive array (React)

Hello, I am currently working on the random quote machine project (https://www.freecodecamp.org/learn/front-end-libraries/front-end-libraries-projects/build-a-random-quote-machine)

I’m attempting to load a json (https://raw.githubusercontent.com/JamesFT/Database-Quotes-JSON/master/quotes.json) and interact with it as an array using bracket notation so that I can generate a random quote using quotesArray[Math.floor(Math.random()*quotesArray.length)];
I’ve successfully accessed the Json using

componentDidMount(){
fetch(‘https://raw.githubusercontent.com/JamesFT/Database-Quotes-JSON/master/quotes.json’)
.then( resp => resp.json())
.then((data)=> {
this.setState({
quotes: data
});
})
.catch((error)=> console.error(error));
}

and then posting it in my render() function using .map as follows (the {…} is irrelevant code):

render(){
return(
{…}
{this.state.quotes.map((quote)=>{
return(<p>{quote.quoteText + ’ - ’ + quote.quoteAuthor}</p>);
})}
{…}

The map function successfully prints all of the quotes. However, despite my best efforts I can’t figure out how to turn what I retrieve from the json into an array I can access and interact with. I’ve never worked with JSON’s before, so I’m willing to bet that’s where my misunderstanding lies. I wish to only use React in this project, no jQuery. Please help me understand what I don’t understand. I encourage ELI5 but anything will do. Thank you!!

I don’t really understand your issues;
as you stated:

meaning that state.quotes is in fact a valid Array, and you are interacting with (mapping and printing content).

Care to explain what is the issue you are having?

Happy coding :slight_smile:

I guess I didn’t really explain the problem. My bad. Hahah. So basically everything prints out properly if I use the code above. However if I do something like this (excuse bad format, I’m on my phone replying to this):

render(){
return(
{…}
<div>
{this.state.quotes[0]}
{…}
);
}

Will throw an error that this.state.quotes[0] is undefined. At some point while messing around with different variations of assigning this.state.quotes what I extracted from the json in the fetch function would sometimes come out as {object, Object} or something of that nature.

My problems are:

  1. I can’t figure out how to create an array from the json that I can reference using bracket indexes
  2. I don’t understand how to extract a json that is an array of objects and convert it into an array of objects that I can interact with to assign properties of said objects to state (such as

    this.setState({
    text: {this.state.quotes[arbitraryQuoteIndex].quoteText},
    author: {this.state.quotes[arbitraryQuoteIndex].quoteAuthor}
    });

    note: quoteText and quoteAuthor are the property names from the json file linked to above

Does that help?

Ok, now I see the issue, and before moving on allow me to clarify an issue:

  • your data is ALREADY a fully workable array that you can manipulate, access and interact with.
    its an array of objects : [{}, {}, {}, ...]

The reason why your code is not working is that you are trying to access it before the you have actually fetched the data!

Remember that JS don’t wait for your fetch function to be completed before moving on to the render part of your code.

to solve it, all you have to do is pretty much “wait” till the data is loaded, this is conveniently also a good UX practice (show some loading indicator while you are at it).

It’s good practice to have a loading and an error state tracked, I made a quick demo to show you a very basic example, hope it will help :+1:

That’s extremely helpful, thank you! I forgot to mention or explain why I wanted to be able to interact with the array. So my initial state looks like this:

constructor(props){
super(props);
this.state= {
loading: false,
text: ‘’,
author: ‘’,
color: ‘’,
quotesHistory: ,
quoteNumber: 0,
quotes:
};
}

However, according to the project the page should have a quote and author displayed on the first load. Will I be able to interact with the fetched data before rendering rather than going straight to the return statement?

edit

I have an additional question. I set my render to have an if-else statement returning “loading” if loading is true, or returning the JSX otherwise. If I call

{<p>{this.state.quotes}</p>}

inside my div, I get an output of ’ [object Object],[object Object], etc… '. I don’t understand why this happens? Shouldn’t it be able to just print out the array as is? Do I need to parse the json or something?

edit #2

I figured out how to interact with the data before rendering and returning. I defined componentWillMount() instead of componentDidMount() and used my quote generation function inside componentWillMount after the fetch completed. Thanks for your help! I’m still curious as to why when you print an array of objects it prints out as [object Object]?