How to update the page after call Axios Successful ? React - reactjs

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);
});
}

Related

DOMException: Failed to execute 'open' on 'XMLHttpRequest': Invalid URL in react

Suhu/Guru, help me
componentDidMount() {
axios
.get(API_URL + "products")
.then((res) => {
const menus = res.data;
this.setState({ menus });
})
.catch((error) => {
console.log(error);
});
}
render() {
console.log(this.state.menus);
return (
and my API in Local Server
export const API_URL = "http://localhost:3004";
and thi's my problem
enter image description here
Your result URL is "http://localhost:3004products" you must to append '/' after API_URL
May be It is making request as "http://localhost:3004products", add '/' in-between URL.
Either add '/' before product or behind URL of API_URL
componentDidMount() {
axios
.get(API_URL + "/products") // Change
.then((res) => {
const menus = res.data;
this.setState({ menus });
})
.catch((error) => {
console.log(error);
});

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 })};
})
}))

Axios get inside a .then is not working as intended

I am using axios to make a http request. Inside the .then() i am using another axios call. Finally, I have a third then() which is supposed to run after the second then but it is actually not doing so.
let assets = [];
export const initAssets = () => {
return dispatch => {
dispatch(setLoadingToTrue());
axios.get('https://....json')
.then(response => {
for(let key in response.data) {
assets.push(response.data[key]);
}
})
.then(() => {
const token = '...';
assets.forEach((cur) => {
axios.get('...' + cur.ticker + '/quote?token=' + token)
.then(response => {
console.log(response);
cur.price = response.data.latestPrice;
})
})
})
.then(() => {
dispatch(initAllAssets(assets));
dispatch(setLoadingToFalse());
})
.catch(error => {
console.log(error);
dispatch(setLoadingToFalse());
})
}
}
The dispatch on the last .then are being executed before the axios request in the second then is completed. How can I make the last then run only after the second axios request is completed?
You can make use of Promise.all to return the response to next .then block and it will be called once all the promises have resolved in the second .then
let assets = [];
export const initAssets = () => {
return dispatch => {
dispatch(setLoadingToTrue());
axios.get('https://....json')
.then(response => {
for(let key in response.data) {
assets.push(response.data[key]);
}
})
.then(() => {
const token = '...';
const promises = [];
assets.forEach((cur) => {
promises.push(axios.get('...' + cur.ticker + '/quote?token=' + token)
.then(response => {
console.log(response);
cur.price = response.data.latestPrice;
}))
})
return Promise.all(promises);
})
.then(() => {
dispatch(initAllAssets(assets));
dispatch(setLoadingToFalse());
})
.catch(error => {
console.log(error);
dispatch(setLoadingToFalse());
})
}
}

componentDidMount not sending data after setting state

I am decoding a token to get the current users email address and setting to facultyEmail state and sending that to the backend to get a response. But facultyEmail is empty because componentDidMount is asynchronous ,it works outside the componentDidMount() but I don't know any way to handle the axios get request with params outside the componentDidMount i dont have event to invoke it.Thanks for the help
componentDidMount() {
const token = localStorage.usertoken;
const decoded = jwt_decode(token);
this.setState({
facultyEmail: decoded.email
});
axios
.get("faculty/Course", {
params: {
facultyEmail: this.state.facultyEmail
}
})
.then(res => {
this.setState({
class: res.data
});
})
.catch(err => {
console.log(err);
});
console.log("courses", this.state.facultyEmail);
}
The setState is asynchronous. You have to use setState callback or async/await
using callback
componentDidMount() {
const token = localStorage.usertoken;
const decoded = jwt_decode(token);
this.setState({
facultyEmail: decoded.email
}, () => {
axios
.get("faculty/Course", {
params: {
facultyEmail: this.state.facultyEmail
}
})
.then(res => {
this.setState({
class: res.data
});
})
.catch(err => {
console.log(err);
});
console.log("courses", this.state.facultyEmail);
});
}
using async/await
async componentDidMount() {
try {
const token = localStorage.usertoken;
const decoded = jwt_decode(token);
await this.setState({
facultyEmail: decoded.email
});
const res = await axios.get("faculty/Course", {
params: {
facultyEmail: this.state.facultyEmail
}
})
this.setState({
class: res.data
});
console.log("courses", this.state.facultyEmail);
} catch (err) {
console.log(err);
}
}
You are using same email you are using in setState to make the API call, there is no need for two setStates. That would cause us anomalies and is not a recommended practice. You can do this in two ways:
Way 1:
componentDidMount() {
const token = localStorage.usertoken;
const decoded = jwt_decode(token);
axios.get("faculty/Course", {
params: {
facultyEmail: decoded.email
}
}).then(res => {
this.setState({
class: res.data,
facultyEmail: decoded.email
});
}).catch(err => {
console.log(err);
});
}
render() {
console.log(this.state.class, this.state.facultyEmail);
// This will have the values from setstate triggered inside axios.
return(
<div> Sample </div>
)
}
Alternate approach:
loadDataFromApi(email) {
axios.get("faculty/Course", {
params: {
facultyEmail: email
}
}).then(res => {
this.setState({
class: res.data
});
}).catch(err => {
console.log(err);
});
}
componentDidMount() {
const token = localStorage.usertoken;
const decoded = jwt_decode(token);
this.setStats({
facultyEmail: decoded.email
}, () => {
// The callback function would reflect the updated email.
this.loadDataFromApi(this.state.facultyEmail);
});
}
Why not just store facultyEmail in memory until the 2nd setState, avoiding the first one? The axios call is async, so you'll need to put the console.log in the render function (and you should only log it once it's actually in state).
componentDidMount() {
const token = localStorage.usertoken;
const decoded = jwt_decode(token);
const facultyEmail = decoded.email;
axios
.get("faculty/Course", { params: { facultyEmail } })
.then(res => { this.setState({ class: res.data, facultyEmail }); })
.catch(err => { console.log(err); });
}
render() {
if (this.state.facultyEmail) console.log("courses", this.state.facultyEmail);
return ();
}

React - Fetch multiple apis

I want to make a get request to multiple apis at the same time from 2 different urls, and then I want to just update the array "items" in the state with the new property "img", not to overwrite it. I want to keep and properties in the first request.
Here is my try.
componentDidMount(){
let url = ``;
let url2 = ``
fetch(url,{
method: 'GET'
})
.then((response)=> response.json())
.then((responseJson) => {
const newItems = responseJson.items.map(i => {
return{
itemId: i.itemId,
name: i.name,
};
})
const newState = Object.assign({}, this.state, {
items: newItems
});
console.log(newState);
this.setState(newState);
})
.catch((error) => {
console.log(error)
});
fetch(url2,{
method: 'GET'
})
.then((response)=> response.json())
.then((responseJson) => {
const newImg = responseJson.item.map( data=> {
return{
img: data.picture.url
};
})
const newState = Object.assign({}, this.state, {
items: newImg
});
console.log(newState);
this.setState(newState);
})
.catch((error) => {
console.log(error)
});
}
You absolutely can call two seperate APIs. The problem that you are having is that the API call that is returning last is overwriting the data that was saved from the first API call. Here is the code that will fix this.
componentDidMount(){
let api1 = `https://myapiexample1.com`;
let api2 = `https://myapiexample2.com`;
let promise1 = fetch(api1)
.then(response => response.json())
.then(json => json.items.map(item => {
return {
itemId: item.itemId
name: item.name
}
}))
let promise2 = fetch(api2)
.then(response => response.json())
.then(json => json.items.map(item => {
return {
img: item.img
}
}))
Promise.all([promise1, promise2])
.then(results => results[0].concat(results[1]))
.then(items => this.setState({itmes}))
}
An alternative approach which is not as clean, but is similar to what you are currently doing is to make sure to include the old state when adding new items to the state:
this.setState({
items: newItems.concat(this.state.items)
})
Use Promise.all():
var p1 = Promise.resolve(3);
var p2 = 1337;
var p3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, "foo");
});
Promise.all([p1, p2, p3]).then(values => {
console.log(values); // [3, 1337, "foo"]
});
Ref: https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
You can use Promise.all, it will resolve when all promises are ok or reject if any fails.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Resources