React set a state to the result of an API call - javascript

I'm making a call to a getTime function which returns the datetime, but for some reason the state I specify is not being updated, am I misunderstanding how this works? Do I need to await the result?
import * as React from 'react';
import {getTime} from '../utilities/time-helper'
export default class Landing extends React.Component {
constructor(props) {
super(props);
this.state = {
london: null,
paris: null
};
}
componentDidMount() {
this.setState({ london: getTime("Europe/London") });
this.setState({ paris: getTime("Europe/Paris") });
}
render() {
return (
<div>
<h1>London Time: {this.state.london}</h1>
<h1>Paris Time: {this.state.paris}</h1>
</div>
);
}
}
// time-helper.js
export function getTime(timezone) {
let url = 'http://worldtimeapi.org/api/timezone/' + timezone;
fetch(url)
.then(res => res.json())
.then((out) => {
return out.datetime
})
.catch(err => { throw err });
}

Yes, exactly, it's a fetch, so you gotta wait for the result and set the state only then, so you could do smth like:
componentDidMount() {
getTime('Europe/London')
.then((response) => this.setState({ london: response });
}

Related

How to set JSON array to state in React?

I have this bellow App.js code:
import React, { Component } from 'react';
import axios from 'axios'
class Axios extends Component {
constructor() {
super();
this.state = {
item : '',
}
}
componentDidMount() {
axios.get('https://restcountries.com/v3.1/capital/lima')
.then( response => {
const data = response.data.map(( data )=>{
this.setState({
item : data
});
});
})
.catch( error => {
alert( error );
});
}
prepare() {
console.log( this.state.item );
}
render() {
return (
<div>{this.prepare()}</div>
)
}
}
export default Axios;
My goal is to get the common name from this API: https://restcountries.com/v3.1/capital/lima
Now on componentDidMount() method, I need to set the API return data to the item state so that I can loop through using the prepare method.
But I don't have any idea how to set the API return array JSON data to the item state?
Update your state.item to a blank array.
constructor() {
super();
this.state = {
item : [],
}
}
In componentDidMount(), update the code to accept response :
componentDidMount() {
axios.get('https://restcountries.com/v3.1/capital/lima')
.then( response => {
this.setState({
item : response.data
});
})
.catch( error => {
alert( error );
});
}
In render(), you can use map on state.item and can loop on it.
render() {
return (
<div>{this.state.item.map(data,index)=>(
//some UI mapping to each `data` in `item` array
)}</div>
)
}
You just have to do assing response.data to item as:
Live Demo
componentDidMount() {
axios
.get("https://restcountries.com/v3.1/capital/lima")
.then((response) => {
this.setState({
item: response.data
})
})
.catch((error) => {
alert(error);
});
}
You should check this out.
import React, { Component } from "react";
import axios from "axios";
class Axios extends Component {
constructor() {
super();
this.state = {
item: []
};
}
componentDidMount() {
axios
.get("https://restcountries.com/v3.1/capital/lima")
.then((response) => {
this.setState({
item: response && response.data
});
})
.catch((error) => {
alert(error);
});
}
prepare() {
return <div>{console.log("Item", this.state.item)}</div>;
}
render() {
return <div>{this.prepare()}</div>;
}
}
export default Axios;

multiple API calls in one componentDidMount using Axios in react

Here is my React js code for a single API call for a date range picker. now I want to call multiple API in React with componentDidMount Method is it possible if yes how can do that
import React,{ Component} from "react";
import axios from 'axios'
class PostList extends Component{
constructor(props) {
super(props)
this.state = {
posts: []
}
}
componentDidMount(){
axios.get('http://127.0.0.1:8000/betweendays')
.then(response => {
this.setState({
posts:response.data
})
console.log(response.data)
})
}
render() {
const {posts} = this.state
return (
<div>
<h1>get call in React js</h1>
{
posts.map(post => <div key = {post.id}>{post.id} </div>)
}
</div>
)
}
}
export default PostList```
Using .then() method to create chain of the requests..
componentDidMount() {
axios.get('http://127.0.0.1:8000/betweendays')
.then(response => {
this.setState({
posts: response.data
})
return response.data; // returning response
})
.then(res => {
// do another request Note we have the result from the above
// getting response returned before
console.log(res);
})
// Tag on .then here
.catch(error => console.log(error))
}
You can add more apis in componentDidMount as u want.
componentDidMount(){
axios.get('http://127.0.0.1:8000/betweendays')
.then(response => {
this.setState({
posts:response.data
})
console.log(response.data)
})
axios.get('link')
.then(response => {
this.setState({
posts:response.data
})
console.log(response.data)
})
}

react axios no response

i'm getting absolutely no response from calling my api in react:
constructor(props) {
super(props);
this.state = {
team: {}
}
}
getData() {
axios.get('http://game.test/api/characters')
.then(response => this.setState({ team: response.data.characters }));
}
componentDidMount() {
this.getData();
console.log(this.state);
}
the state is empty and if I console.log anything in .then, the console is also empty (like that part of the code is not reachable).
Also on Network tab everything seems to be okay (status 200 & correct data).
setState is async so in console.log(this.state) will execute before this.getData() in the componentDidMount. if you want to log the fetch result/error put log in getData with async/await:
constructor(props) {
super(props);
this.state = {
team: {},
error: ""
}
}
getData = async () => {
await axios.get('http://game.test/api/characters')
.then(response => this.setState({ team: response.data.characters }))
.catch(error => this.setState({error: error}))
console.log(this.state) //log fetch result/error
}
componentDidMount() {
this.getData();
console.log(this.state) //log init state
}
Try this, it will work
App.js
import Child from "./Comp/Chid";
export default function App() {
return (
<div className="App">
<Child />
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
Comp/Child.js
import React from "react";
import axios from "axios";
class Child extends React.Component {
constructor(props) {
super(props);
this.state = {
team: {}
};
}
async getData() {
await axios
.get("https://jsonplaceholder.typicode.com/posts")
.then((response) => {
console.log(response);
this.setState({ team: response.data.characters });
});
}
componentDidMount() {
this.getData();
console.log(this.state);
}
render() {
return <div>Hello</div>;
}
}
export default Child;
i dont see much problem with your code try the following if it helps
first try to console.log(response) before updating the state
try async getData () and await axios since you are fetching asynchronous operation

How to update state from a react mapping component

I have an api which i want to filter the data and place the filterd into a state
export default class ModifyPage_Single extends React.Component {
constructor(props) {
super(props)
this.state = {data:[],idd:""}
}
componentWillMount() {
fetch("removed api")
.then(response => response.json())
.then((data) =>{
this.setState({data:data})
})
}
render() {
const test = this.state.data.map((e) => { if(e.ID === this.props.location.productdetailProps.productdetail) {this.setState({idd:e.PP})} })
But i keep getting this error Unhandled Rejection (Error): Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
How can i solve so that the fitered out api goes into the state?
Thanks in advance
you should update in componentMount, not in render():
export default class ModifyPage_Single extends React.Component {
constructor(props) {
super(props);
this.state = { data: [], idd: "" };
}
componentWillMount() {
fetch("removed api")
.then((response) => response.json())
.then((data) => {
this.setState({ data: data });
data.forEach((e) => {
if (e.ID === this.props.location.productdetailProps.productdetail) {
this.setState({ idd: e.PP });
}
});
});
}
render() {
return null;
}
}
You can update the state in lifecycle methods, updating it in render is anti pattern
componentDidMount() {
fetch("removed api")
.then(response => response.json())
.then((data) =>{
this.setState({data:data})
const iddObj = data.find((el) => el.ID === this.props.location.productdetailProps.productdetail)
if(iddObj ){
this.setState({idd:iddObj.PP})
}
})
}

How to access state value from one component to other function(not component) which is in separate file? React js

This is my Home Component:
import React from 'react';
import { getData } from '../../../util/network';
export default class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
page: 1,
};
}
async componentWillMount() {
const val = await getData();
}
render() {
return() {
// jsx stuffs
}
}
}
This is a file called network.js: // which is a function
export const getData = () => {
const { page } = this.state; // this is undefined now
const url = `http://randomuser.in/${page}`;
fetch(url)
.then(res => res.json())
.then(res => {
return res;
})
.catch(error => {
console.log('error:', error);
});
};
How to access state value of page in my network.js file?
You should pass page state as a parameter to your function :
async componentDidMount() {
const val = await getData(this.state.page);
}
Note that I replaced componentWillMount by componentDidMount which is prefered for doing async actions.
export const getData = (page) => {
const url = `http://randomuser.in/${page}`;
fetch(url)
.then(res => res.json())
.then(res => {
return res;
})
.catch(error => {
console.log('error:', error);
});
};
You shouldn't be depending on this.state in your function. Its not a good practice. You should just pass the parameters/arguments you will need in that function.
Example
const val = await getData(this.state.page);
export const getData = (page) => {
// use page argument that passed
//...
};

Categories