Infinite loop on react ComponentDidUpdate - reactjs

I have a model called Event, after updating the Event, when I try to update the change to the view with componentDidUpdate it keeps looping forever (infinite loop). I have searched and saw people that had the same problem but I can't seem to get it working.
here is my componentDidUpdate inside EventComments component
componentDidUpdate() {
axios
.get(
"http://localhost:9000/events/" +
this.props.match.params.id +
"/eventcomments"
)
.then((response) => {
this.setState({ event: response.data });
this.setState({ eventcomments: response.data.eventcomments });
})
.catch(function (error) {
console.log(error);
});
}
Please what should I do to get this infinite loop to stop?

You need to wrap your event in a conditional. Reference from the docs:
componentDidUpdate(prevProps) {
// Typical usage (don't forget to compare props):
if (this.props.userID !== prevProps.userID) {
this.fetchData(this.props.userID);
}
}
Your example:
componentDidUpdate(prevProps) {
if(prevProps.id !== this.props.match.params.id){
axios
.get(
"http://localhost:9000/events/" +
this.props.match.params.id +
"/eventcomments"
)
.then((response) => {
this.setState({ event: response.data });
this.setState({ eventcomments: response.data.eventcomments });
})
.catch(function (error) {
console.log(error);
});
}
}

after so many tries, I have managed to make it work. but, if you know a better way of doing it than this, please let me know.
Here is my what I did
componentDidUpdate(prevProps, prevState) {
if (prevState.event === this.state.event) {
axios
.get(
"http://localhost:9000/events/" +
this.props.match.params.id +
"/eventcomments"
)
.then((response) => {
this.setState({ event: response.data });
})
.catch(function (error) {
console.log(error);
});
}
}

Related

Axios - catch() possibility to pass props?

I am trying to setState for loading after a response error has been catched by the axios .catch() function, but so far, it only allows the error props itself. Is there a way to pass the state props so I can setState after an error has been catched?
this.setState({loading: true})
axios.get(`${wordpressUrl}/wp-json/wp/v2/pages/727?password=${password}`)
.then(res => {
this.setState({
data: res.data,
loading: false,
visible: true
})
})
.catch((error) => {
if (error.response) {
alert("Invalid password.");
this.setState({ loading: false });
this.forceUpdate();
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
}
});
Code example is what I would ideally want to achieve.
EDIT: 1
I tried the following, but the .then function just skips the response.status else and continues to catch() the error:
.then(response => {
if(response.status === 403) {
alert("Invalid password.");
this.setState({ loading: false });
this.forceUpdate();
} else {
this.setState({
data: response.data,
loading: false,
visible: true
})
}
})
.catch(error => {
if (error.response) {
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
}
});
I AM NOT GONNA SET THIS AS AN ANSWER, SO I'LL EDIT MY QUESTION:
It wasn't clear enough for me how to pass any props to the catch to so on make a detailed and user friendly catching method.
So I did the following:
.catch(error => {
this.setState({loading: false})
console.clear()
console.log(error);
})
If you want to send a variable to the catch block you can use throw inside of one of the then block. You can use throw like a return statement.
throw myProps.
You will then get myProps as the argument you declared for the catch block.

How to save single object into state, from json end point axios

UPDATE:
axios
.get("https://cors-anywhere.herokuapp.com/" + "https://api.linkedin.com/v2/me", config)
.then(response => {
this.setState({profile: response.data})
})
^ saved the object in state for me :) Thanks everyone!!
I am a newbie to react. I am trying to save a single object from a JSON end point into the state of my react component. I am definitely returning the JSON data in the response. However it is not being saved into the state, can you see where I am going wrong?
// State needed for the component
constructor(props) {
super(props);
this.state = {
profile: {},
};
}
// Grabs profile data from the json url
private getProfile() {
let config = {
headers: {'Authorization':'Bearer AQVVEqNXTWV....'}
}
axios
.get("https://cors-anywhere.herokuapp.com/" + "https://api.linkedin.com/v2/me", config)
.then(response =>
response.data(profile => ({
id: `${ profile.id }`
}))
)
.then(profile => {
this.setState({
profile
});
})
// We can still use the `.catch()` method since axios is promise-based
.catch(error => this.setState({ error, isLoading: false }));
}
JOSN data returned:
{
"localizedLastName": "King",
"id": "fm0B3D6y3I",
"localizedFirstName": "Benn"
}
Your first then block looks wrong.
Try to do console.log there like this:
.then(response => {
console.log(response); // I am sure that you will get profile inside response.data or something similar
return response.data(profile => ({
id: `${ profile.id }`
}));
})
If you want to keep your first then that "prepares the data", then you should return a promise instead of data, like:
let config = {
headers: {'Authorization':'Bearer AQVVEqNXTWV....'}
}
axios
.get("https://cors-anywhere.herokuapp.com/" + "https://api.linkedin.com/v2/me", config)
.then(response => {
return new Promise((resolve, reject) => {
resolve( {
id: `${ response.data.id }`
});
});
}
)
.then(profile => {
this.setState({
profile
});
})
// We can still use the `.catch()` method since axios is promise-based
.catch(error => this.setState({ error, isLoading: false }));
Here's an example of how that would work:
I do believe that's a bit of an overkill though and you should be able to just set your state in the first then such as:
this.setState({profile: {id : response.data.id}});
Try to remove the second then, like this:
axios
.get("https://cors-anywhere.herokuapp.com/" + "https://api.linkedin.com/v2/me", config)
.then(response => {this.setState({ profile: response.data })};
})
}))

Updating object in react under componentDidMount

I able to get the right data from my API node.js server. however when i try to setstate the object to render it it keeps returning null
i tried to use spread operator before the response but it still not working
import React, { Component } from "react";
import axios from "axios";
class Profile extends Component {
constructor(props) {
super(props);
this.state = {
UserData: null,
isLoading: false,
error: null
};
}
componentDidMount() {
this.setState({ isLoading: true });
axios
.get(
`http://localhost:5000/api/v1/profile/${this.props.match.params.platform}/${this.props.match.params.gamertag}`
)
.then(response => {
console.log(response.data);
})
.then(response => {
this.setState({
UserData: response.data,
isLoading: false
});
})
.catch(error => this.setState({ error, isLoading: false }));
}
render() {
const { isLoading, UserData } = this.state;
if (isLoading) {
return <p>Loading ...</p>;
}
console.log(UserData);
return <div>{UserData}</div>;
}
}
export default Profile;
when i try to log. the UserData log "null", but the "console.log(response.data)" works fine so it have to do something with the setState
when you chain data method like .then(), the following chained methods automatically receive value returned by the previous function.
getData
.then(res => console.log(res))
console.log itself will return nothing, thus the following .then() method will receive nothing.
getData
.then(res => console.log(res))
.then(data => console.log(data))
So if you do this, the second console.log() will log null.
You can fix it by returning something in your console.log step:
getData
.then(data => {
console.log(data);
return data;
})
.then(data => this.setState({ data: data }));
And the second console.log() will log properly.
You don't need two chain two then()'s, you can get the response and set the state after .then()
componentDidMount() {
this.setState({ isLoading: true });
axios
.get(
`http://localhost:5000/api/v1/profile/${this.props.match.params.platform}/${this.props.match.params.gamertag}`
)
.then(response => {
this.setState({
UserData: response.data,
isLoading: false
});
})
.catch(error => this.setState({ error, isLoading: false }));
}

State not updating correctly with get request from API

I am making two api GET requests, and with both I would like the state to update. For some reason it is only updating with the values from the first GET request.
I have tried using the spread operator to update the state and add in new values to current state (categories) from the GET requests.
axios // first get request
.get(
"LINK_TO_API"
)
.then(res => {
this.setState({
...this.state.categories,
categories: res.data.data
});
})
.catch(function(error) {
console.log(error);
});
axios // second get request
.get(
"LINK_TO_API"
)
.then(res => {
this.setState({
...this.state.categories,
categories: res.data.data
});
})
.catch(function(error) {
console.log(error);
});
I am currently getting 10 values from first GET request and would like to get the total of 20 values when I map through categories.
You will never get 20 values, due to are not appending values, you just are overwriting categories values in each call.
this.setState({
...this.state.categories,
categories: res.data.data
});
Here categories: res.data.data is being overwrited.
Just modify your code to:
axios
.get(
"LINK_TO_API"
)
.then(res => {
this.setState((state) => ({
...state,
categories: [...state.categories, ...res.data.data]
}));
})
.catch(function(error) {
console.log(error);
});
First of all, your spread operator is wrong, you have to wrap it into array categories: [...this.state.categories, ...res.data.data]. Also I advice you to wait all your post loaded and then set them to state:
Promise.all([axios.get('LINK_TO_API'), axios.get('LINK_TO_API_2')])
.then(allYourPosts => {
this.setState({ /* set it to state */ });
})
.catch((error) => {
console.log(error);
});
Assuming that categories is an array, you are overriding one array with another array.
In the code below, i am always returning a new array, and concating the new array with the previous array.
axios // first get request
.get('LINK_TO_API')
.then(res => {
this.setState({
categories: [...this.state.categories, ...res.data.data]
});
})
.catch(function(error) {
console.log(error);
});
axios // second get request
.get('LINK_TO_API')
.then(res => {
this.setState({
categories: [...this.state.categories, ...res.data.data]
});
})
.catch(function(error) {
console.log(error);
});

How to update the page after call Axios Successful ? React

so I'm doing a project that uses Axios with Json-server, but I have a problem, every time I do a Patch, I have to give F5 on the homepage for it to update, I wanted know how I could do it so that it did not happen, and automatically.
My Patch:
onSubmitDate = event => {
const newUrl = prompt("Please with new URL:");
const personCurrent = event.target.value;
axios.patch(`http://localhost:3004/employee/${personCurrent}`, {
url_git: newUrl
})
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error);
});
}
My Get:
componentDidMount() {
axios
.get("http://127.0.0.1:3004/employee")
.then(response => this.setState({ employee: response.data }));
}
Someone would can help me?
I am assuming the update is on the component you are handling.
For you to create a re-render of your component, you can simply set the state. See more here
What is the format of your response? Does it include the updated data you wish to display? If that is the case, it's easy, simply do a setState in your then:
onSubmitDate = event => {
const newUrl = prompt("Please with new URL:");
const personCurrent = event.target.value;
axios.patch(`http://localhost:3004/employee/${personCurrent}`, {
url_git: newUrl
})
.then(response => {
console.log(response);
this.setState({employee: response.data})
})
.catch(error => {
console.log(error);
});
}
If the response is not providing the data you want updated in your component, your can simply do your GET of whatever data you want in the then of your PATCH and set the state on it's response. So something like this:
onSubmitDate = event => {
const newUrl = prompt("Please with new URL:");
const personCurrent = event.target.value;
axios.patch(`http://localhost:3004/employee/${personCurrent}`, {
url_git: newUrl
})
.then(response => {
console.log(response);
axios.get("http://127.0.0.1:3004/employee")
.then(response => this.setState({ employee: response.data }));
})
.catch(error => {
console.log(error);
});
}

Resources