ReactJS - Storing API data in state - reactjs

New to React and JS in general so I apologize for the simplistic nature of this question.
I'm attempting to store a single child's name from my API in React's state but I must be doing something incorrectly with the JSON as this state is never updated.
If someone could explain what I'm doing incorrect and the best way to accomplish this, I'd very much appreciate it. My code almost mirrors this but I can't seem to figure out whats wrong here.
https://www.robinwieruch.de/react-fetching-data/
import React, { Component } from 'react';
import Child from '../../Components/Child/Child'
class MyKids extends Component {
constructor(props) {
super(props);
this.state = {
kidsName: '',
};
}
componentDidMount() {
fetch( 'http://localhost:3001/api/kids' )
.then( response => response.json())
.then(data => this.setState({kidsName: data[0].name}));
}
render() {
const { kidsName } = this.state;
return (
<div className = 'col-sm-12'>
<ul>
<p>{ kidsName }</p>
<Child
kidsName={ kidsName }
/>
</ul>
</div>
);
}
}
export default MyKids;
JSON Response:
{"success":true,"data":[{"_id":"5b10610c827ea427b05581b9","name":"Nick"},{"_id":"5b115bc8827ea427b05581bb","name":"Trevor"}]}

In your code the processing of the second then in the fetch should be:
componentDidMount() {
fetch( 'http://localhost:3001/api/kids' )
.then( response => response.json())
.then(data => this.setState({kidsName: data.data[0].name}));
}
For clarity you might change it for:
componentDidMount() {
fetch( 'http://localhost:3001/api/kids' )
.then( response => response.json())
.then(result => this.setState({kidsName: result.data[0].name}));
}

The mistake is here:
.then(data => this.setState({kidsName: data[0].name}));
This should be
.then(res => this.setState({kidsName: res.data[0].name}));
instead, because data in the first snippet has the shape { data: [...] }.

Related

React problems when i try to make an api call using fetch

i have a problem i try to make an api call to https://randomuser.me/api/ using fetch and i try to setstate my value array to the api data and then to map and i cant figure out where is the problem in my code because i get some errors
import "./App.css";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
value: [],
};
}
componentDidMount() {
fetch("https://randomuser.me/api/")
.then((res) => res.json())
.then((data) => this.setState({ value: data }));
}
render() {
return (
<div>
<p>test</p>
<div className="map">
{this.state.value.map((item) => (
<p>{item.gender}</p>
))}
</div>
</div>
);
}
}
export default App;
The endpoint you are fetching from sends the response as an object, when you try to setState with the call this.setState({ value: data }) it sets the entire response object as this.state.value. That is why you get the error "this.state.value.map is not a function" because this.state.value was replaced as an object by the setState call.
I believe you want the value of results property from the response object which has the correct array data for the user. You can simply change the setState call to set the value as data.results.
componentDidMount() {
fetch("https://randomuser.me/api/")
.then((res) => res.json())
.then((data) => this.setState({ value: data.results }));
}

Fetch some data from an api with React

Im trying to fetch some data from an api but for some reason it's not working, i also tried with Object.key.
I have been doing api fetch a couple of times but i guess i don't understand this JSON format
Here is my code:
class CryptoNews extends Component {
constructor(props){
super(props);
this.state = {
news: []
}
}
componentDidMount(){
fetch('https://min-api.cryptocompare.com/data/v2/news/?feeds=cryptocompare,cointelegraph,coindesk&extraParams=YourSite')
.then(res => res.json())
.then(data => this.setState({
news: data
})
)}
render() {
return (
<div>
{this.state.news.map((key) => (
<div key={key.id}>
<h2>{key.body}</h2>
</div>
))}
</div>
)
}
}
You need to take the Data property from the response object.
So:
news: data.Data
You are trying to get the Data array and set it to this.state.news.
The format of JSON message is like this.
{
"Type":100,
"Message":"News list successfully returned",
"Promoted":[],
"Data":[],
"RateLimit":{},
"HasWarning":false
}
your componentDidMount method should be like following
componentDidMount(){
fetch('https://min-api.cryptocompare.com/data/v2/news/?
feeds=cryptocompare,cointelegraph,coindesk&extraParams=YourSite')
.then(res => res.json())
.then(data => this.setState({
news: data.Data
})
)}

React Display Data from API Fetch & Map

i'm attempting to learn React by making a movie web app. Im trying to pull upcoming movies from a movie api, and display information from it, however i keep getting an error:
Line 37: Expected an assignment or function call and instead saw an
expression no-unused-expressions
Please excuse me as im not too familiar with this framework and im not a JS pro. Heres my code:
export default class Upcoming extends Component {
state = {
upcomingMovies: []
}
fetchUpcoming() {
fetch(`https://api.themoviedb.org/3/movie/upcoming?api_key=${API_KEY}&language=en-US&page=1`)
// We get the API response and receive data in JSON format...
.then(response => response.json())
// ...then we update upcomingMovies State
.then(data =>
this.setState({
upcomingMovies: data.results
})
)
}
componentDidMount(){
this.fetchUpcoming();
}
render() {
return(
<Container>
{ this.state.upcomingMovies.map((upcomingMovie) => {
console.log(upcomingMovie);
const title = upcomingMovie.title;
console.log(title);
<h1>{title}</h1>
})}
</Container>
)
}
}
Map function should return something to generate ui.
export default class Upcoming extends Component {
state = {
upcomingMovies: []
}
fetchUpcoming() {
fetch(`https://api.themoviedb.org/3/movie/upcoming?api_key=${API_KEY}&language=en-US&page=1`)
// We get the API response and receive data in JSON format...
.then(response => response.json())
// ...then we update upcomingMovies State
.then(data =>
this.setState({
upcomingMovies: data.results
})
)
}
componentDidMount(){
this.fetchUpcoming();
}
render() {
return(
<Container>
{ this.state.upcomingMovies.map((upcomingMovie) => (
<h1>{upcomingMovie.title}</h1>
))}
</Container>
)
}
}
You're missing a return statement in the last line of your map function. It should be return <h1>{title}</h1>
You should write fetchUpcoming by using arrow function. So, you can use this.setState() method on scope of fetchUpcoming function. EX:
const fetchUpcoming = async() {
try {
let response = await fetch(
`https://api.themoviedb.org/3/movie/upcoming?api_key=${API_KEY}&language=en-US&page=1`,
);
let responseJson = await response.json();
return this.setState({
upcomingMovies: responseJson.data.results
})
} catch (error) {
console.error(error);
}
}

React doesn't render API data

Im building a recipe App and I got stuck and there is no error display or anything that can help me, Its my first time working with APIS in React and Im a little bit lost thats why im asking.
I´m trying to fetch data from this API and I don´t know why the properties will not show on the screen since I ve another example where it does.
I can see in the console with the React Developer extension that the properties are passed to the state so that´s fine and I dont understand why I cannot access or why it doesnt render.
In the other example doesn't get the data from an API it gets the data from a local object in json. Does it work different when it comes an API? Any idea?
import React, { Component } from "react";
class App extends Component {
constructor(props) {
super(props);
this.state = {
recipes: []
};
}
componentDidMount() {
this.fetchData();
}
fetchData() {
fetch("https://www.themealdb.com/api/json/v1/1/random.php")
.then(response => response.json())
.then(json => {
this.setState({ recipes: json });
})
.catch(error => console.log("parsed error", error));
}
render() {
return <div className="box">{this.state.recipes.strMeal}</div>;
}
}
export default App;
Your code looks okay, but you need to render somehow your backend data:
fetchData() {
fetch("https://www.themealdb.com/api/json/v1/1/random.php")
.then(response => response.json())
.then(json => {
this.setState({ recipes: json.meals });
})
.catch(error => console.log("parsed error", error));
}
render() {
return (
<div className="box">
{this.state.recipes.map(m => <p>{m.strMeal}</p>)}
</div>
);
}
recipes is a json with meals key that is an array. Each element in the array has strMeal key (name of the meal).

React Multiple Fetch from state

so I am trying to fetch my SWAPI json-server twice using the homeworld id to get the homeworld name but I just get "TypeError: Cannot read property 'name' of undefined". Im fairly new to React so if it looks messy im sorry! Thanks in advance!
import React, { Component } from 'react';
import './Card.css';
const person = personID =>
`http://localhost:3008/people/${personID}`
const picture = pictureID =>
`http://localhost:3008/${pictureID}`
// const planet = planetID =>
// `http://localhost:3008/planets/${planetID}`
class Card extends Component {
constructor(props){
super(props);
this.state ={
requestFailed: false,
person: 1,
planet: 4
}
}
componentDidMount(){
fetch(person(this.state.person))
.then(response => {
if(!response.ok) {
throw Error("Network Request Failed");
}
return response
})
.then(d => d.json())
.then(d => {
this.setState({
cardData: d
})
}, () => {
this.setState({
requestFailed: true
})
})
fetch(`http://localhost:3008/planets/${this.state.cardData.homeworld}`)
.then(data => data.json())
.then(data => {
this.setState({
homeData: data
})
})
}
render() {
if(this.state.requestFailed === true) return <p>Error please try
again!</p>
if(!this.state.cardData) return <p>Loading ...</p>
return (
<div className='card'>
<div className='card-content'>
<div className='card-name'>{this.state.cardData.name}</div>
<img src={picture(this.state.cardData.image)}
alt='profile'/>
<p>
<span>Birthday:</span>
<span>{this.state.cardData.birth_year}</span>
</p>
<p>
{/* Note that in order to get the homeworld's name, you have to get the planet name from a different endpoint than the people */}
<span>Homeworld:</span>
<span>{this.state.homeData.name}</span>
</p>
</div>
</div>
);
}
}
export default Card;
It looks like the first problem is that you're attempting to render homeData.name before it's loaded. You should probably have a loading check similar to the cardData loading check. Or you could just render nothing until it's loaded:
{this.state.homeData ?
<span>{this.state.homeData.name}</span> :
<span>Loading...</span>
}
The 2nd problem is that you're doing the second fetch of homeData at the same time as the first fetch. So this line:
fetch(`http://localhost:3008/planets/${this.state.cardData.homeworld}`)
Will always fail because the cardData is not loaded into the state yet when it runs.
What you should do is move it inside the response part of the first request:
fetch(person(this.state.person))
.then(response => {
if(!response.ok) {
throw Error("Network Request Failed");
}
return response
})
.then(d => d.json())
.then(d => {
this.setState({
cardData: d
})
fetch(`http://localhost:3008/planets/${d.homeworld}`)
.then(data => data.json())
.then(data => {
this.setState({
homeData: data
})
})
}, () => {
this.setState({
requestFailed: true
})
})
It would help to extract these into separate functions to clean it up a bit.

Resources