Consume RESTful data with React and Axios - reactjs

how can I retrieve the data from https://api.github.com/search/users?q=jason and render it in React? I tried something like:
constructor(){
this.state = {
data: []
};
}
componentDidMount(){
axios.get("https://api.github.com/search/users?q="+_searchTerm)
.then(res => {
this.setState({
data: _.values(res.data.items)
})
});
}
render() {
const listProducts = this.state.data.map((product) =>
<li key={product.toString()}>{product}</li>
);
return (
<div>
<ul>{listProducts}</ul>
</div>
);
}
but it didn't work. I get the error message:
Unhandled Rejection (Invariant Violation):
Objects are not valid as a React child (found: object with keys {login, id, avatar_url, gravatar_id, ...).
If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons.
so I guess is that I have to convert the response to an array. But I am not too sure how to do it.

You are returning an object rather than a component or a string.
Change this;
const listProducts = this.state.data.map((product) =>
<li key={product.toString()}>{product}</li>
);
to this
// you need to set key to a unique string like id
const listProducts = this.state.data.map((product) =>
<li key={product.id}>{JSON.stringify(product)}</li>
);

Related

ReactJS - Can't access properties in object from a fetch

I'm doing a fetch to an API and it's returning the data fine, but when I try access the properties, it returns:
Error: Objects are not valid as a React child (found: object with keys {breeds, categories, id, url, width, height}). If you meant to render a collection of children, use an array instead.
myFetch.jsx
import React, {Component} from "react"
class myFetch extends Component {
state={
data:[]
}
componentDidMount(){
const url = "xxxxxxxxxxxxxxxxxxxxxxx"
fetch(url)
.then(r=>r.json())
.then(data=>{
this.setState({data:data})
// console.log(data)
})
.catch(e=>console.log(e))
}
render(){
const {data} = this.state
console.log(data[0])
return (<p>{data[0]}</p>)
}
}
export default myFetch
EDIT
"data" in the state is initialized to an array. Therefore, I should have iterated through the array during the render as
{data.map(d => d.url)} and access whichever property I desire as shown below:
render(){
const {data} = this.state
console.log(data)
return (<p>{data.map(d=>d.url)}</p>)
}
Your data on the state doesn't have any element on 0 index. That's why you getting that undefined error. You can check if it exists before trying to render it.
Something like that:
render() {
const { data } = this.state;
if (data[0]) {
console.log(data[0]);
return <p>{data[0].url}</p>;
}
return null;
}

Cannot read property of data null in ReactJs when fetching from JSON

I am new to react andtrying to fetch JSON data in React JS but getting this error:
TypeError: Cannot read property 'data' of null
My code is :
import React from 'react';
export default class FetchJson extends React.Component {
componentDidMount()
{
fetch('https://api.myjson.com/bins/9i63i')
.then((response) => response.json())
.then((findresponse) =>{
this.setState({ data: findresponse })
//console.log(this.state.data);
//console.log(findresponse.DesignName);
})
}
render() {
return(
<ul>
{this.state.data.map((x,i) => <li key={i}>{x.DesignName}</li>)}
</ul>
);
}
}
You can see the json data here: http://myjson.com/9i63i
I want to retrieve value for key DesignName which is part1 which is not happening.
See the commented lines: both gives me the value. But when i try to access it inside return method inside render. I get error : TypeError: Cannot read property 'data' of null in this line:
{this.state.data.map((x,i) => <li key={i}>{x.DesignName}</li>)}
How to solve this?
DesignName is not an array in the response.
You can define your state like this:
state = {
data: null
}
And display the DesignName using inline if with logical && operator to solve null problem.
render() {
return (
<div>
DesignName: { this.state.data && this.state.data.DesignName}
</div>
);
}
Codesandbox
You can use an isLoading flag while waiting for your api call to finish.
state = {
data: null,
isLoading:true
}
render() {
if(this.state.isLoading) {
return(<div>loading</div>);
}
return(
<ul>
{this.state.data.map((x,i) => <li key={i}>{x.DesignName}</li>)}
</ul>
);
when your api call has finished, you can update the state like this:
this.setState({ data: findresponse, isLoading:false })

Not able to render data from state into the React Component

I am trying to call Firebase and fetch the data in the form of JSON and then pass the objects of the JSON array to some other react-native component.
I am able to successfully make a call to Firebase and then fetch the array of JSON objects. Then later I am storing that list of JSON objects inside the STATE variable and then later trying to pass the object one by one to another react-native component.
Code:
class DisplayCardInformation extends Component
{
const itemsRef = db.ref('firebaseLink/');
state = {
listDataFromDB: null,
lastKey: null
};
componentDidMount()
{
itemsRef.on('value', ( snapshot ) => {
var data = snapshot.val();
this.setState({
listDataFromDB : snapshot.val(),
});
var keys = Object.keys(data);
keys.forEach((key) =>
{
this.setState({
lastKey: key
});
});
});
}
render() {
this.state.listDataFromDB.map((listDataItem) => {
return(
<CardInformation listItem = {listDataItem} />
);
});
}
}
export default DisplayCardInformation;
I am trying to pass the information to the CardInformation.
Error:
TypeError: TypeError: null is not an object (evaluating 'this.state.listDataFromDB.map')
This error is located at:
in DisplayCardInformation (at Home.js:33)
You need to set the initial value of the state to any array like:
state = {
listDataFromDB: []
};
What is happing in your case is that, when your component renders for the first time, it passes null to the child component.

API Call Returns Data But Not Render

My console.log shows axios call returns data [object object] but it shows undefined when I try to render the data. Any ideas?
```
class CourseDetail extends Component {
state={
ID: this.props.match.params.ID,
course:[]};
componentDidMount(){
this.runSearch();
}
runSearch=async()=>{
const response= await axios.get('API\?{this.props.match.params.ID}')
this.setState({course: response.data});
//console.log shows course=[object object]
console.log("course="+response.data);
}
render(){
//course is undefined below
const course= this.state.course.map(item=> <div>(item.SUBJECT)</div>)
return (
<div>
{course}
</div>
); }
};
export default CourseDetail;
As #HolyMoly mentioned in the comments, you may need to stringify the response as JSON as well before logging it depending on what the API is returning. There's also a syntax error in your map function, you are using parentheses instead of curly braces to render the value. Depending on the structure of your data response, something like this may work:
class CourseDetail extends Component {
state={
ID: this.props.match.params.ID,
course:[]};
componentDidMount() {
axios.get('API\?{this.props.match.params.ID}')
.then(res => res.json())
.then(res => {
console.log("course="+res.data);
this.setState({course: res.data})
})
}
render(){
//course is undefined below
const course= this.state.course.map(item=> <div>{item.SUBJECT}</div>)
return (
<div>
{course}
</div>
); }
};
export default CourseDetail;
This depends on whether or not the data you are mapping is an object or an array of course. If it is in fact an object, you can map over the keys instead:
const course= Object.keys(this.state.course).map(item=> <div>{item.SUBJECT}</div>)

When I set component's state with concat I receive error: Warning: Each child in an array or iterator should have a unique "key" prop.

My React component renders a twitter stream. The original version works correctly, but the componentDidMount method mutates the component's state:
(Original) components/Stream.js
import React, { Component } from 'react';
import { Button } from 'react-bootstrap';
class Stream extends Component {
constructor() {
super();
this.state = { streamItems: [] }
}
componentDidMount() {
fetch('/tweets')
.then(res => res.json())
.then(tweets => this.setState({ streamItems: tweets }));
}
render() {
return (
<div>
<h1>Tweets</h1>
<div className='stream-items'>
{this.state.streamItems.map(tweet =>
<div key={tweet.id}>{tweet.text}</div>
)}
</div>
<Button
className='btn-remove'
onClick={() => this.props.removeStream(this.props.stream.id)}
>
Remove Stream
</ Button>
</div>
)
}
}
export default Stream;
To prevent the component's state being mutated I setState using concat instead:
components/Stream.js (updated method only)
componentDidMount() {
fetch('/tweets')
.then(res => res.json())
.then(tweets => this.setState({
streamItems: this.state.streamItems.concat([tweets])
}))
}
I now receive the error:
Warning: Each child in an array or iterator should have a unique
"key" prop.
This is confusing as I have set the key in the component's render method.
Warning: Each child in an array or iterator should have a unique "key" prop.
streamItems: this.state.streamItems.concat([tweets])
Its look like tweets is not having id.Its coming undefined.So,React throwing an error. Or you need to spread it
streamItems: this.state.streamItems.concat([...tweets])
Note:
You don't need to use concat.You can do like this.
streamItems:[...this.state.streamItems,tweets]

Resources