TypeError: Cannot destructure property results of 'undefined' or
'null'.
at displayCartTotal
const displayCartTotal = ({results}) => {
};
const fetchBill = () => {
const apiHost = 'https://randomapi.com/api';
const apiKey = '006b08a801d82d0c9824dcfdfdfa3b3c';
const apiEndpoint = `${apiHost}/${apiKey}`;
fetch(apiEndpoint)
.then( response => {
return response.json();
})
.then(results => {
console.log(results.results)
displayCartTotal();
})
.catch(err => console.log(err));
};
You get the error because you aren't passing results into displayCartTotal like displayCartTotal(results)
You are calling displayCartTotal() with no parameter, but it expects an object. See commented line below:
const displayCartTotal = ({results}) => {
};
const fetchBill = () => {
const apiHost = 'https://randomapi.com/api';
const apiKey = '006b08a801d82d0c9824dcfdfdfa3b3c';
const apiEndpoint = `${apiHost}/${apiKey}`;
fetch(apiEndpoint)
.then( response => {
return response.json();
})
.then(results => {
console.log(results.results)
displayCartTotal(); //<--- this is the offending line
})
.catch(err => console.log(err));
};
You should pass results as a parameter like this: displayCartTotal(results).
Hope that solves it for you :)
Related
I am trying to access the res.data.id from a nested axios.post call and assign it to 'activeId' variable. I am calling the handleSaveAll() function on a button Click event. When the button is clicked, When I console the 'res.data.Id', its returning the value properly, but when I console the 'activeId', it's returning null, which means the 'res.data.id' cannot be assigned.
I just need to assign the value from 'res.data.id' to 'metricId' so that I can use it somewhere else in another function like save2() function.
Does anyone have a solution? Thanks in advance
const [activeId, setActiveId] = useState(null);
useEffect(() => {}, [activeId]);
const save1 = () => {
axios.get(api1, getDefaultHeaders())
.then(() => {
const data = {item1: item1,};
axios.post(api2, data, getDefaultHeaders()).then((res) => {
setActiveId(res.data.id);
console.log(res.data.id); // result: e.g. 10
});
});
};
const save2 = () => {
console.log(activeId); // result: null
};
const handleSaveAll = () => {
save1();
save2();
console.log(activeId); // result: again its still null
};
return (
<button type='submit' onClick={handleSaveAll}>Save</button>
);
This part of code run sync
const handleSaveAll = () => {
save1();
save2();
console.log(activeId); // result: again its still null
};
but there you run async
axios.get(api1, getDefaultHeaders())
.then(() => {
You can refactor your code to async/await like this:
const save1 = async () => {
const response = await axios.get(api1, getDefaultHeaders());
const response2 = await axios.post(api2, { item1: response.data.item1 }, getDefaultHeaders());
return response2.data.id;
};
const save2 = (activeId) => {
console.log(activeId); // result: null
};
const handleSaveAll = async () => {
const activeId = await save1();
save2(activeId);
setActiveId(activeId);
console.log(activeId); // result: again its still null
};
or to chain of promises, like this:
const save2 = (activeId) => {
console.log(activeId); // result: null
};
const save1 = () => {
return axios.get(api1, getDefaultHeaders())
.then(({ data }) => {
const data = {item1: item1,};
return axios.post(api2, {item1: data.item1}, getDefaultHeaders())
})
.then((res) => res.data.id);
};
const handleSaveAll = () => {
save1()
.then((res) => {
setActiveId(res.data.id);
console.log(res.data.id); // result: e.g. 10
return res.data.id;
})
.then(save2);
};
I am not able to access the returned object property, Please tell me why its returning undefined when data is object and giving correct value.
This is function created to sendHTTPRequest based on data.
import { countryCap } from "./capitalizingFunc.js";
export const sendHTTPRequest = (country) => {
const capitalisedCountry = countryCap(country);
return fetch(
`https://covid-19-coronavirus-statistics.p.rapidapi.com/v1/total?country=${capitalisedCountry}`,
{
method: "GET",
headers: {
"x-rapidapi-key": "3b0f2e00ebmsh95246403d9540c9p1506d4jsn3c44ce26f745",
"x-rapidapi-host": "covid-19-coronavirus-statistics.p.rapidapi.com",
},
}
)
.then((response) => {
const newResponce = response.json();
return newResponce;
})
.catch((err) => {
console.error(err);
});
};
This is constructor class
export class casesDataFetcher {
constructor(countryName) {
sendHTTPRequest(countryName)
.then((response) => {
return response.data;
})
.then((data) => {
this.country = data.location;
this.cases = data.confirmed;
this.recovered = data.recovered;
this.deaths = data.deaths;
console.log(this);
return this;
});
}
}
This is execution function
import { casesDataFetcher } from "./casesDataFetcher.js";
export const screenDataShower = (country) => {
const dataStorage = [];
const globalInfected = document.querySelector(".infected h2");
const globalActive = document.querySelector(".active h2");
const globalDeaths = document.querySelector(".deaths h2");
const globalRecovered = document.querySelector(".recovered h2");
const globalCountries = document.querySelector(".countries h2");
let promise = new Promise(function (resolve, reject) {
const recordedData = new casesDataFetcher(country);
console.log(recordedData);
resolve(recordedData);
});
return promise.then((data) => {
console.log(typeof data);
console.log(typeof data);
console.log(data.cases); // NOT WORKING GIVING UNDEFINED
globalInfected.textContent = `${nn.cases}`;
globalActive.textContent = data.cases - data.recovered - data.deaths;
globalDeaths.textContent = data.deaths;
globalRecovered.textContent = data.recovered;
globalCountries.textContent = 219;
});
};
I also tried to convert the data to JSON again but still I was not able to access the property of returned data in screenDataShower
you're calling sendHTTPRequest inside casesDataFetcher's constructor, from your code there's no guarantee data is resolved when you access it
extract sendHTTPRequest into a new function and wrap into a promise
export class casesDataFetcher {
constructor(countryName) {
this.countryName = countryName
}
fetch = () => {
return new Promise((res, rej) => {
sendHTTPRequest(this.countryName)
.then((response) => {
return response.data;
})
.then((data) => {
this.country = data.location;
this.cases = data.confirmed;
this.recovered = data.recovered;
this.deaths = data.deaths;
console.log(this);
res(this);
});
})
}
}
make screenDataShower function async then you can await data from fetch function in casesDataFetcher, this way it can guarantee data is there when you access it
import { casesDataFetcher } from "./casesDataFetcher.js";
export const screenDataShower = async (country) => {
const dataStorage = [];
const globalInfected = document.querySelector(".infected h2");
const globalActive = document.querySelector(".active h2");
const globalDeaths = document.querySelector(".deaths h2");
const globalRecovered = document.querySelector(".recovered h2");
const globalCountries = document.querySelector(".countries h2");
const _casesDataFetcher = new casesDataFetcher(country)
const data = await _casesDataFetcher.fetch()
console.log(typeof data);
console.log(typeof data);
console.log(data.cases); // NOT WORKING GIVING UNDEFINED
globalInfected.textContent = `${nn.cases}`;
globalActive.textContent = data.cases - data.recovered - data.deaths;
globalDeaths.textContent = data.deaths;
globalRecovered.textContent = data.recovered;
globalCountries.textContent = 219;
};
The problem is that the json method of your response returns a promise instead of plain JSON. So you should change the call of the json method in your sendHTTPRequest function to something like:
.then((response) => {
const newResponse = response.json().then((jsonResponse) => jsonResponse);
return newResponse;
})
Attempting to make an inquiry which depends on input esteem. I am utilizing countries rest programming interface. The wished yield is the parsed information from API which is templated by handlebars markup. It would be ideal if you clarify in what capacity can fix my code. Much obliged to you.
import markupAdd from "../templates/markup.hbs";
const divInfo = document.querySelector("#main-container");
const search_input = document.querySelector(".input-field");
let search_term = "";
let countries;
const fetchCountries = () => {
countries = fetch(
"https://restcountries.eu/rest/v2/all?fields=name;flag;capital;population;languages"
).then((res) => res.json());
};
const showCountries = () => {
divInfo.innerHTML = "";
fetchCountries();
countries
.filter((country) =>
country.name.toLowerCase().includes(search_term.toLowerCase())
)
.map((item) => markupAdd(item))
.join("");
divInfo.insertAdjacentHTML("beforeend", infoBlock);
};
search_input.addEventListener("input", (e) => {
search_term = e.target.value;
showCountries();
});
handlebars
<div id="country-container">
<p class="country">{{name}}</p>
<img src="{{flag}}" alt="{{name}}" width="600" height="400">
<div id="info-container">
<p class="capital">Capital: {{capital}}</p>
<p class="population">Population: {{population}} </p>
<ul class="langs">
{{#each languages}}
<li class="language">Languages: {{name}}</li>
{{/each}}
</ul>
</div>
</div>
At the present time, after inputed any letter I am getting this kind of error
apiInfo.js?b765:22 Uncaught TypeError: countries.filter is not a function
at showCountries (apiInfo.js?b765:22)
at HTMLInputElement.eval (apiInfo.js?b765:28)
The fetchCounries function is not returning anything, one approch to solve the issue will be following.
Convert the Function to the async function
and then return the data your will get.
const fetchCountries = async () => {
let countries = await fetch(
"https://restcountries.eu/rest/v2/all?fields=name;flag;capital;population;languages"
);
let country = await countries.json();
return country;
};
const showCountries = () => {
divInfo.innerHTML = "";
fetchCountries().then(countries =>{
countries
.filter((country) =>
country.name.toLowerCase().includes(search_term.toLowerCase())
)
.map((item) => markupAdd(item))
.join("");
divInfo.insertAdjacentHTML("beforeend", infoBlock);
}).catch(err => {
console.log(err)
})
};
Async Function also returns a promise so later you can handle this using then catch block
to do it without the async await and do it more clear, you can do something like this
const fetchCountries = () => {
fetch(
"https://restcountries.eu/rest/v2/all?fields=name;flag;capital;population;languages"
)
.then((res) => res.json())
.then((data) => {
showCountries(data);
})
.catch((err) => {
console.log(err);
});
};
const showCountries = (countries) => {
divInfo.innerHTML = "";
countries
.filter((country) =>
country.name.toLowerCase().includes(search_term.toLowerCase())
)
.map((item) => markupAdd(item))
.join("");
divInfo.insertAdjacentHTML("beforeend", infoBlock);
};
Change your function like this :
async function fetchCountries() {
response = await fetch ("https://restcountries.eu/rest/v2/all?fields=name;flag;capital;population;languages");
return await response.json();
};
And where you are calling the function , just use .then to get the data.
fetchCountries().then().catch();
I can console.log and see the array I created but as soon as I attempt to access it, I get undefined.
async componentDidMount() {
// fetch goal data for display
let response = await fetchWithToken("http://localhost:8080/api/getGoals");
let goalData = await response.json();
goalData = await goalData.filter(skill => skill.Skill === "CS_en");
// get info from people API with distinct list rather than every row
let people = new Set([]);
goalData
.filter(element => element.UpdatedBy !== null)
.forEach(element => {
people.add(element.UpdatedBy);
});
people = Array.from(people);
// call peopleAPI
const peopleObj = await peopleAPI(people);
console.log("peopleObj :", peopleObj);
console.log("peopleObj[0] :", peopleObj[0]);
}
Here is the peopleAPI where I'm calling another api and getting a list of user info.
const peopleAPI = people => {
return new Promise(function(resolve, reject) {
// get people API info
const peopleObj = [];
const apiPromises = [];
if (people) {
people.forEach(empid => {
const apiPromise = fetch(
`https://someApiCall/${empid}`
)
.then(res => res.json())
.then(res => {
peopleObj.push({
empid: res.id,
name: res.name.preferred ? res.name.preferred : res.name.full
});
})
.then(() => apiPromises.push(apiPromise));
});
// once all promises have been resolved, return a promise with the peopleObj
Promise.all(apiPromises).then(() => {
resolve(peopleObj);
});
}
});
};
export default peopleAPI;
Results of console.logs
Don't use push inside fetch.then, just return its value, and then push it to apiPromises`
const peopleAPI = people => {`
return new Promise(function(resolve, reject) {
// get people API info
const apiPromises = [];
if (people) {
people.forEach(empid => {
const apiPromise = fetch(`https://someApiCall/${empid}`)
.then(res => res.json())
.then(res => {
return {
empid: res.id,
name: res.name.preferred ? res.name.preferred : res.name.full
}
});
apiPromises.push(apiPromise)
});
Promise.all(apiPromises).then((data) => {
resolve(data);
});
}
});
};
export default peopleAPI;
Or even simpler and readable
const peopleAPI = people => {`
const apiPromises = people.map(empid => {
return fetch(`https://someApiCall/${empid}`)
.then(res => res.json())
.then(res => ({
empid: res.id,
name: res.name.preferred ? res.name.preferred : res.name.full
}));
});
return Promise.all(apiPromises)
};
I have a function that fetches data from the url and is supposed to return it:
const fetchTableData = () => {
fetch('https://api.myjson.com/bins/15psn9')
.then(result => result.json())
.then(data => {
return data;
})
}
export default fetchTableData;
The problem is that when i import this function and try to use it, it always returns undefined.
When i console log the data inside the function itself, you can see it is available. The function just doesn't work when i try to import it.
What is the problem here? Why does it work that way?
Try this =) You have to return something from the fetchTableData function also.
const fetchTableData = () => {
const fetchedData = fetch('https://api.myjson.com/bins/15psn9')
.then(result => result.json())
.then(data => {
return data;
})
return fetchedData;
}
export default fetchTableData;
Or you can just return it like this:
const fetchTableData = () => {
return fetch('https://api.myjson.com/bins/15psn9')
.then(result => result.json())
.then(data => {
return data;
})
}
export default fetchTableData;
In your code you were not returning from the fetchTableData function. Only from the the second then() callback. When a function has no return value, undefined will be returned.
Try this instead:
const fetchTableData = () => {
const myResponse = fetch('https://api.myjson.com/bins/15psn9')
.then(result => result.json())
.then(data => {
return data;
})
return myResponse;
}
export default fetchTableData;
What now happens is the following:
The response return by the second then() function is returning the data.
We are saving this data in a variable, named myResponse.
We are now returning this value from the function fetchTableData.
You need to either store data in a global variable or assign any variable to fetch to get return data.
//First way
fetch('https://api.myjson.com/bins/15psn9')
.then(result => result.json())
.then(data => {
console.log("data",data);
});
//Second way
let binData = null;
fetch('https://api.myjson.com/bins/15psn9')
.then(result => result.json())
.then(data => {
binData = data;
console.log("binData", binData);
});
Here is the working example.