Saving data from JSON end point - javascript

I am trying to map over the returned json and save the id into profile/profiles. However it does not seem to be mapping over the the data correctly, id: ${ profile.id } this bit needs to be changed? Any help is much appreciated.
Is their a online tool that can help with me this?
API request:
// Grabs company data from the json url
private getProfiles() {
let config = {
headers: {'Authorization':'Bearer AQVVEqNXTWVYPpPYivKNWVO8jsTx2eveV3kBg'}
}
axios
.get("https://cors-anywhere.herokuapp.com/" + "https://api.linkedin.com/v2/me", config)
.then(response =>
response.data.map(profile => ({
id: `${ profile.id }`
}))
)
.then(profiles => {
this.setState({
profiles
});
})
// We can still use the `.catch()` method since axios is promise-based
.catch(error => this.setState({ error, isLoading: false }));
}
Json data returned:
{
"localizedLastName": "King",
"id": "fm0B3D6y3I",
"localizedFirstName": "Benn"
}
When I console log the response.data

If the only data returned from your endpoint is the JSON you posted, then you don't have an array to map over.
You have a single object.
I've never used the axios library before, but looking at the source code response.data should be the JSON-parsed responseText from the XHR request:
https://github.com/axios/axios/blob/4f189ec80ce01a0275d87d24463ef12b16715d9b/lib/adapters/xhr.js#L51-L53
https://github.com/axios/axios/blob/4f189ec80ce01a0275d87d24463ef12b16715d9b/lib/defaults.js#L61
And now I see that you have posted response.data and it matches what I'd expect.
With that in mind I'd suggest handling it like this:
// Grabs company data from the json url
private getProfiles() {
let config = {
headers: {'Authorization':'Bearer AQVVEqNXTWVYPpPYivKNWVO8jsTx2eveV3kBg'}
}
axios
.get("https://cors-anywhere.herokuapp.com/" + "https://api.linkedin.com/v2/me", config)
.then(response => ({
id: profile.id
}))
.then(profiles => {
this.setState({
profiles
});
})
// We can still use the `.catch()` method since axios is promise-based
.catch(error => this.setState({ error, isLoading: false }));
}
What you're getting back is a single profile though. If you need profiles to be an array you'll need to put the response in an array.

I don't get it, what you are trying to do. In the map you have a callback function, but as I see you wrote there an object. If you are wanting to rewrite the current profile's id then write this:
response.data.map(profile => ({
profile.id = `${ profile.id }`;
}))
But if you want it to make a variable then this:
response.data.map(profile => ({
let id = `${ profile.id }`;
}))

Related

my error object is undefined when i`m using rtk query with try/catch

first of all i want to apologize for my title. I just dont know how to describe my problem.
I am trying to get a bad response from my server and when I try to display that my object is undefined
I have a base query methods here:
export const accountSlice = apiSlice.injectEndpoints({
endpoints: builder => ({
login: builder.mutation({
query: credentials => ({
url: 'account/login',
method: 'POST',
body: { ...credentials },
})
}),
register: builder.mutation({
query: credentials => ({
url: 'account/register',
method: 'POST',
body: { ...credentials },
})
})
})
})
My handle submit on register page ->
const [register, { isLoading, isError }] = useRegisterMutation();
const handleSubmit = async (e) => {
e.preventDefault();
try {
const result = await register({ name, nickName, email, password }).unwrap();
setRegisterResponse(result);
} catch (error) {
setRegisterResponse(error);
}
}
And my logic to show it. When i use console.log(registerResponse) it returnes two logs in console - first object is empty, second object with properties ->
{
isError &&
<h2>
Ooops.. something went wrong:
{
console.log(registerRespnse)
}
</h2>
}
Error in google console
You shouldn't need to call a setRegisterResponse state setter, because that response will just be available for you:
// see data and error here
const [register, { isLoading, isError, data, error }] = useRegisterMutation();
As why it logs undefined once: first the query finishes with an error (which will rerender the component and already fill error I showed above and set isError) and then the Promise resolves and your custom code sets your response local state, which causes a second rerender (and only on the second render, response is set)

How to manipulate strings inside array from a fetch response?

I am looking for some assistance with my fetch response from the Online Movie Database API . I am able to succesfully get a response to log in the console, which is what I want. However I am trying to manipulate the response.
I want to pull the most popular shows from the API (API sends 100 titles), and trim it down to 8 titles. I did that using the .splice method. It returns an array of 8 strings representing a title id.
Example: '/title/tt11198330'
Lastly I want to trim each 8 of the strings so it gets rid of the /title/ and all I have left is tt11198330. I am trying to do this inside the .then and when I console.log that forEach that is saved as 'trimmer' it gives me undefined instead of the trimmed result I was intending. But if I console.log the element in the forEach it does show the trimmed strings. Any idea why its undefined, and is there maybe a better way to go about this?
// fetch for most popular shows
const options = {
method: 'GET',
headers: {
'X-RapidAPI-Key': 'Z2EvqnO4xwmsh2eY3rMTIV2ivj5hp1QsuGUjsnrYp69UBS4EI5',
'X-RapidAPI-Host': 'online-movie-database.p.rapidapi.com'
}
};
fetch('https://online-movie-database.p.rapidapi.com/title/get-most-popular-tv-shows?currentCountry=US&purchaseCountry=US&homeCountry=US', options)
.then(response => response.json())
.then(response => {
const list = response.splice(0, 8)
let trimmer = list.forEach(element => console.log(element.slice(7, 17)))
console.log(trimmer)
})
.catch(err => console.error(err));
because you are using forEach and it doesn't return data, use map instead.
fetch('https://online-movie-database.p.rapidapi.com/title/get-most-popular-tv-shows?currentCountry=US&purchaseCountry=US&homeCountry=US', options)
.then(response => response.json())
.then(response => {
const list = response.splice(0, 8)
let trimmer = list.map(element => element.slice(7, 17))
console.log(trimmer)
})
.catch(err => console.error(err));

Firebase push get key with sdk 9 modular approach

As the question asks I'm attempting to get the key after I push to a firebase db.
push(dbRef, formState)
.then((resp) => {
console.log(resp);
})
.catch(error => {
Alert.alert(error)
})
The above console.log gives me the full url of the data pushed. In example:
"https://example.firebaseio.com/organization/asdfasdfasdf/members/-N08ScImBoOckVIRu-AU". I need the key only: `-N08ScImBoOckVIRu-AU`
I incorrectly attempted:
push(dbRef, formState)
.getKey()
.then((resp) => {
})
.catch(error => {
Alert.alert(error)
})
This gives an error.
How can I accomplish this?
If you split the push() call from the actual writing of the data, you can get the key like this:
const newRef = push(dbRef);
console.log(newRef.key);
set(newRef, formState);

Axios GET request (from backend) with object as parameter

I'm having a lot of trouble using axios to send requests to this API, which accepts parameters in an object fashion:
GET https://api.osrsbox.com/items?where={ "name": "Abyssal whip", "duplicate": false }
The main problem is that axios automatically encodes the string. Searching for solutions in StackOverflow, i've came to this:
const item = "Abyssal Whip"
const config = {
paramsSerializer: (params) => {
return querystring.stringify(params, { arrayFormat: 'brackets' });
},
params: {
where : {
name: item,
duplicate: false
}
}
}
axios.get("https://api.osrsbox.com/items", config).then( (resp) => {
[...]
})
This results in the following request:
https://api.osrsbox.com/items?where=%7B%22name%22:%22Abyssal%20Whip%22,%22duplicate%22:false%7D
I would like to know what am i doing wrong. Thanks in advance.
PS: I'm making requests from a Node.js environment/server.
That's a really weird format that your API accepts. But I suppose it's what you've got to work with...
It looks to me like you might be successful by changing the relevant part of your code to:
where: JSON.stringify({
name: item,
duplicate: false
})
(I hope the spaces in your example request aren't required, if they are then this won't work)
you have to use npm package "qs"
npm i qs
make a object which has all your request body params eg -
const requestBody = {
....... ;
}
now while making Axios request -
Axios.get("https://api.osrsbox.com/items", qs.stringyfy(requestBody), config)
.then(res => console.log(res)
.catch(err => console.log(err))

Vuex: Fetch data with axios based on already fetched data

I'm fetching data from an external API via axios in the Vuex store, which gives me an array with objects - let's say - cities.
Each city has a zipCode, which I need to fetch city details with.
I want to add that details-object as a new key to the cities array.
Right now I'm fetching all cities and have another Vuex action to fetch the city details.
ACTION to fetch all cities
fetchCities: ({ commit, state, dispatch }) => {
let baseUrl = "https://my-url/cities";
let config = {
headers: {
accept: "application/json",
Authorization: ...
},
params: {
param1: "a",
param2: "b"
}
};
axios
.get(baseUrl, config)
.then(function(response) {
commit("UPDATE_CITIES_RAW", response.data.items);
})
.catch(function(error) {
console.log(error);
});
dispatch("fetchCityDetails");
},
MUTATION after fetching all cities
UPDATE_CITIES_RAW: (state, payload) => {
state.citiesRaw = payload;
},
Each object in that array has a zipCode, which I'm fetching details about this city with.
I tried to loop the citiesRaw array inside the action to fetch the details and commit a change for each iteration, but the array from the state is empty at this point, because the action gets called before the mutation.
ACTION to fetch city details
fetchCityDetails: ({ commit, state }) => {
let baseUrl = "https://my-url/cities/"
let config = {
headers: {
accept: "application/json",
Authorization: ...
}
};
// citiesRaw is empty at this point
state.citiesRaw.forEach(e => {
let url = baseUrl + e.zipCode;
axios
.get(url, config)
.then(function(response) {
commit("UPDATE_CITY_DETAILS", {
response: response.data,
zipCode: e.zipCode
});
})
.catch(function(error) {
console.log(error);
});
});
},
What are the best ways to wait for the first fetch and then update the array?
Should I even use the same array or create a new one to begin with?
Or is there even a better way to fetch based on fetched data in the Vuex store?
UPDATE
After fixing the dispatching before the async function even finished (thanks, #Y-Gherbi), I also refactored the way of fetching the details:
Component dispatches  fetchCities
in fetchCities action: commit  UPDATE_CITIES
in UPDATE_CITIES mutation: .map on the payload and create new object -> push all to state.cities
in fetchCities action: loop state.cities & dispatch  fetchCityDetails(zipCode) for each city
in fetchCityDetails action: commit  UPDATE_CITY_DETAILS
in UPDATE_CITY_DETAILS mutation: .map on state.cities  and add  cityDetails object  to the referred city object
new actions
fetchCities: ({ commit, state, dispatch }) => {
let baseUrl = "https://my-url/cities";
let config = {
headers: {
accept: "application/json",
Authorization: ...
},
params: {
param1: "a",
param2: "b"
}
};
let url = baseUrl;
axios
.get(url, config)
.then(function(response) {
commit("UPDATE_CITIES", response.data.items);
state.cities.forEach(city => {
dispatch("fetchCityDetails", city.zipCode);
});
}
})
.catch(function(error) {
console.log(error);
});
},
fetchCityDetails: ({ commit }, zipCode) => {
let baseUrl = "https://my-url/cities";
let config = {
headers: {
accept: "application/json",
Authorization: ...
},
};
let url = baseUrl + "/" + zipCode;
axios
.get(url, config)
.then(function(response) {
commit("UPDATE_CITY_DETAILS", {
cityDetails: response.data,
zipCode: zipCode
});
})
.catch(function(error) {
console.log(error);
});
}
new mutations
UPDATE_CITIES: (state, cities) => {
// I don't need all data & I want to rename the keys from the response,
// so I create a new object
cities = cities.map(city => {
let obj = {};
obj.zipCode = city.zip_code
obj.key1 = city.key_1;
obj.key2 = city.key_2;
return obj;
});
state.cities.push(...cities);
},
UPDATE_CITY_DETAILS: (state, payload) => {
let cities = state.cities;
// add one details-object for each city
cities = cities.map(city => {
if (city.zipCode == payload.zipCode) {
city.cityDetails = payload.cityDetails;
}
return city;
});
state.cities = cities;
}
The question remains: Is there a better/more optimized approach to this kind of fetching?
I think that there are much better and elegant ways to deal with this but to simply help you with the bug (looping over an empty array that's expected to be an array of cities)
fix
Try moving the dispatch function to the next line after the commit function. The array (citiesRaw) is empty because you are calling the action before the data is fetched (because axios.get is an async operation)
alternative solution
As you said, the cities are displayed in a table with expandable rows, which are used to display the city details. Fetching 100-1000 cities is quite a lot of data but it's still one call to the back-end. But looping over all these items and doing a request for every one of them could be problematic from a performance and bandwidth (if that's the correct term for large data usage) perspective.
Personally, I would handle each request whenever the user actually needs this data. In your case whenever the user clicked on a row to expand it.
Storing it in the store?
Whenever you want to store the city details in the store is up to you. You could just keep it in the component but personally, I would use it as some kind of cache mechanism.
When the user clicked on a row, check if the details are already fetched
if(!state.cityDetails[key]) {
axios.get()
.then(res => {
// Commit a mutation that saves the fetched details
})
.catch((error) => {
// Handle error
})
} else {
// Use the 'cached' cityDetails
}
Your store could look something like this:
{
cityDetails: {
keyCouldBeIdOrZipcode: {...},
anOtherAlreadyFetchedCity: {...},
}
}
sorry for the typos and bad formatting. Typing code on a phone is horrible

Categories

Resources