React bad Header Request - javascript

I'm trying to build new Header Request by looping inside the API and getting specific data. What I'm trying to achieve is to get some specific data and to put in Request Payload. But the result that I'm achieving with my code seems to be wrong.
API looks like:
id: 12345
profileID: 3456
name: "Profile Name"
details: [
0: {
detailID: 4556
progressID: 5678
comment:
0: {
id: 63434
commentNumber: 34
image: 'image.jpg'
}
}
]
documents:
0: {
id: 3567
docId: 6753
docName: 'doc.pdf'
}
and what I need to achieve is:
id: 12345
details: [
0: {
detailId: {
0: 3567
}
document: {
0: 3567
}
}
]
So, tried to move inside api:
.then((response) => {
const getID: Object.values(response).map(result => result.details.map(test => test.detailID));
const getComm = Object.values(response).map(result => result.details.map(test => test.comment.map(
cId => cId.id
)));
const getDoc = Object.values(response).map(result => result.documents.map(test => test.id));
setProfile({
id: getID,
details: {
getComm, getDoc
}
})
});
and I'm achieving the result like that:
id: {
0: {
0: 12345
}

you have used Object.values, instead try with Object.keys and proceed further

Related

Axios returns a nested array with single objects after using Promise.all

I am using axios and my goal is to execute a get request inside a map function. The following function accept an array of Id's. The first step was to create a simple get function that will be called inside the MAP function.
In the try catch block, I set the Promise.all() method.
// Get imaged exercices
export const getImagedExercices = async array => {
let getIds = async element => {
let array = await axios.get(`http://localhost:3000/api/get-exercice-by-id/${element}`);
let data = await array.data;
return data;
}
try {
const arrayEx = array.map(item => item.exerciceId);
let mappedResult = await Promise.all(arrayEx.map(async element => await getIds(element)));
return mappedResult;
}
catch (error) {
console.log(error);
return error;
}
}
The problem is that I get an array that for each existing item is wrapped inside another array that contains the actual object...
[
[
{
id: 'clcj22d650002sbdkmmobh33l',
bodyPart: 'waist',
equipment: 'body weight',
gifUrl: 'http://d205bpvrqc9yn1.cloudfront.net/0001.gif',
name: '3/4 sit-up',
target: 'abs'
}
],
[
{
id: 'clcj22d650002sbdkmmobh33l',
bodyPart: 'waist',
equipment: 'body weight',
gifUrl: 'http://d205bpvrqc9yn1.cloudfront.net/0001.gif',
name: '3/4 sit-up',
target: 'abs'
}
],
[
{
id: 'clcj22d650007sbdk9ncyidv1',
bodyPart: 'upper legs',
equipment: 'body weight',
gifUrl: 'http://d205bpvrqc9yn1.cloudfront.net/1512.gif',
name: 'all fours squad stretch',
target: 'quads'
}
]
]
This is the response of the entire function...

Create new object from array

I'm trying to create new object with different properties name from Array.
Array is:
profiles: Array(1)
0:
column:
name: "profileName"
title: "Profile name"
status: "Active"
I want to create new function that return object with two properties:
id: 'profileName',
profileStatus: 'Active'
The function that I have create is returning only one property as undefined undefined=undefined.
function getProfile(profiles) {
if (!profiles.length) return undefined;
return profiles.reduce((obj, profile) => {
console.log('profiles', profile);
return ({
...obj,
id: profile.column.name,
profileStatus: profile.status,
});
}, {});
}
The function getProfile is taking as input array 'profiles' from outside,
I've just tested here and this seems to be working actually
const getProfile1 = (p) => p.reduce((obj, profile) =>({
...obj,
id: profile.column.name,
profileStatus: profile.status,
}), {});
You can use map as an alternative.
var profiles = [{"column":{"name": "profileName3","title": "3Profile name"},"status": "Active"},{"column":{"name": "profileName","title": "Profile name"},"status": "Active"}];
function getProfile(profiles) {
if (!profiles.length) return undefined;
return profiles.map(function(profile,v){
return {id:profile.column.name,profileStatus: profile.status};
});
}
console.log(getProfile(profiles));
Whenever I use reduce in this way, I usually index the final object by some sort of an id. As noted in another answer, you could use map in this situation as well. If you really want your final data structure to be an object, however, you could do something like this:
/**
* returns object indexed by profile id
*/
const formatProfiles = (profiles) => {
return profiles.reduce((obj, profile) => {
return {
...obj,
[profile.id]: {
id: profile.column.name,
profileStatus: profile.status,
}
};
}, {});
};
const profiles = [
{
id: 0,
status: 'active',
column: {
name: "profile_name_1",
title: "profile_title_1",
},
},
{
id: 1,
status: 'inactive',
column: {
name: "profile_name_2",
title: "profile_title_2",
}
}
];
const result = formatProfiles(profiles);
/**
* Result would look like this:
*/
// {
// '0': { id: 'profile_name_1', profileStatus: 'active' },
// '1': { id: 'profile_name_2', profileStatus: 'inactive' }
// }

Change an object value inside a loop in JavaScript

I have an array of objects like this:
const data = [{
_id:"49847444033",
name:"yoko"
},{
_id:"49847433333",
name:"doira"
}]
I have to change each item name property to something like this :
...
{
_id:"49847433333",
name:{
en:"John"
}
}
My attempt is to loop object like following :
data.forEach((item) => {
item.name = {en:"john"}
console.log(item)
})
But this always console the original item and the name property value is not modified.
const newData = data.map(user => ({ _id: user._id, name: { en: user.name } }))
I created a library to express transformations like this very simply.
const { pipe, fork, get } = require('rubico')
const data =
[ { _id: '49847444033', name: 'yoko'}
, { _id: '49847433333', name: 'doira'}
]
const onData = pipe([
fork({
_id: get('_id'), // data => data._id
name: fork({ en: get('name') }), // data => ({ en: data.name })
}),
console.log,
])
data.map(onData) /*
{ _id: '49847444033', name: { en: 'yoko' } }
{ _id: '49847433333', name: { en: 'doira' } }
*/
I've commented the code above, but to really understand rubico and get started using it, I recommend you read the intuition and then the docs
try somthing like:
const newList = data.map(obj => {
return { _id: obj._id, name: { en: obj.name } }
});
and the newList list is your new data list so you can do it:
data = newList;
EDIT:
if you have more properties you can change the return line to:
return { ...obj, name: { en: obj.name } }
what will happen here, it will deploy all the object properties as they are, and modify the name property, unfortunately, every property you want to modify, you have to re-write it.

I'm trying to map over objects, nested in objects that are nested in an array. What's the best way of tackling this?

I am receiving data from an API containing cryptocurrency market data. When a user searches for crypto the information of that crypto is fetched and added to the state. I would like to have each item that is returned from the API render to the user, slowly making a list of the data and sub-data.
I'm aware of mapping on an array, but cannot seem to get objects mapped (having attempted 'Object.key.map' too)
I have tried to target the items in the object, rather then the full objects returned themselves, but React doesn't seem to like me using uppercase in my code, with the dot notation of getting items from an object (uppercase appears to be required by the API as it returns data with uppercase:
(3) [{…}, {…}, {…}]
0:
XTZ:
USD: 0.9505
__proto__: Object
__proto__: Object
1:
BTC:
USD: 9823.95
__proto__: Object
__proto__: Object
2:
ETH:
USD: 216.81
__proto__: Object
__proto__: Object
length: 3
__proto__: Array(0)
here are results from 3 returned query to the API.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
cryptos: [],
term: '',
error: undefined
};
}
getstuff = (symbol) => {
axios.get(`https://min-api.cryptocompare.com/data/pricemulti?fsyms=${symbol}&tsyms=USD`)
.then(res => {
const crypto = res.data;
console.log(crypto);
if (res.data.Response === 'Error') {
console.log('found error');
const error = res.data.Message;
if (error) {
if (error.includes('toSymbol/s')){
this.setState({error: `We cannot find ${symbol} in our list of cryptos. Please ensure you're using the symbol, not the full name (ie 'BTC', not 'Bitcoin')`})
console.log(this.state);
} else {
this.setState({error: `Hmmmm, we're run into an error, and frankly have no idea what it is.`})
}
}
} else {
this.setState({ cryptos: [...this.state.cryptos, crypto] });
}
})
}
onInputChange = (e) => {
console.log(e.target.value)
this.setState({ term: e.target.value});
}
onFormSubmit = (e) => {
e.preventDefault();
this.getstuff(this.state.term.toUpperCase());
this.setState({term: ''})
}
render() {
return (
<div>
<form onSubmit={this.onFormSubmit}>
<div className="field">
<label>Video Search</label>
<input
type="text"
value={this.state.term}
onChange={this.onInputChange}/>
</div>
</form>
{`you searched ${this.state.term}`}
{this.state.cryptos.map((item,i) => <li key={i}>item</li>)}
{this.state.error && <p>{this.state.error}</p>}
<button onClick={() => {console.log(this.state.cryptos)}}> console log current state </button>
</div>
)
}
}
I'm trying to extract and render the cryptocurrency name that is returned (should match user query), as well as the price (in USD) that is returned with it.
ideally along the lines of
Selection 1: BTC, $9452 at the time of the query.
Selection 2: ETH, $202 at the time of the query.
Selection 3: XTZ, $0.92 at the time of the query.
If i have an object like this:
obj = [
{ name: "Jon", ID: { num: 23, country: "Canada" } },
{ name: "Mary", ID: { num: 28, country: "Russia" } },
{ name: "Jon2", ID: { num: 12, country: "Germany" } }
];
I would iterate like so:
obj.map(element => { Object.keys(element).map( key => console.log(element[key]))})
request ?fsyms=EUR,GBP&tsyms=USD
gives me:
{
"EUR":{ "USD":1.124 },
"GBP":{ "USD":0.03747 }
}
I would iterate it like this:
const data = {
"EUR":{ "USD":1.124 },
"UAH":{ "USD":0.03747 }
};
Object.keys(data).forEach((key, i) => {
console.log(`Selection ${i}: ${key}, $${data[key]["USD"]} at time of query.`);
});
If you add more matches to the internal object, then you can iterate like this:
const data = {
"EUR":{ "USD":1.124, "GBP":0.8991 },
"UAH":{ "USD":0.03747, "GBP":0.03016 }
};
let i = 0;
Object.keys(data).forEach(key => {
const values = data[key];
Object.keys(values).forEach(key2 => {
console.log(`Selection ${++i}: ${key}, ${key2} is $${data[key][key2]}.`);
});
});
Which will result in:
Selection 1: EUR, USD is $1.124.
Selection 2: EUR, GBP is $0.8991.
Selection 3: UAH, USD is $0.03747.
Selection 4: UAH, GBP is $0.03016.

#Ngrx/store: how to query models with relationships

I an Angular 2 app using Redux (with #ngrx/store), I have modeled the store this way:
{
modelA: {
ids: [1, 2],
entities: { 1: { name: "name modelA 1" },
2: { name: "name modelA 2" }
}
},
modelB: {
ids: [5, 8],
entities: { 5: { name: "name modelB 5" },
8: { name: "name modelA 8" },
9: { name: "name modelA 9" }
}
}
}
Basically, I have 2 types of objects: modelA and modelB. This is ok for now.
But I can't find which is the best way to write a relationship between then, representing something like modelA has many modelB (one-to-many). Can I do something like this?
modelAmodelB: {
entities: {
1: [5],
2: [8, 9]
}
}
This is in the root of the store, it's not a child from 'modelA'.
This might work, but how then would I 'query' the modelB from a specific modelA, using #ngrx/store methods? Because if I write a selector function that reads the global state and returns the partial state from modelAmodelB, I don't have access to the rest of the state when I compose my functions. Example:
compose(getModelAEntities(number[]), getModelAModelBRelations(modelA_id: number), getModelAModelBState() );
I can query this using Observable.combineLast
Observable
.combineLatest(
this.store.select('contentContents'),
this.store.select('contents'),
(relations: any, contents: any) => {
return relations.entities[1].map( id => {
return contents.entities[id]
})
}
).subscribe( data => {
console.log(data);
})
But I don't know if this is right: anytime I change modelA entities object (adding a new one, for example), the subscribe() is called, but the output is the same, because neither modelA entity has changed nor its modelB related objects.
PS: I could do the query this way
export const getModelAModelBs = (id) => {
return state =>
state.select( (s: any) => [s.modelAModelB.entities[id], s.modelB.entities])
.distinctUntilChanged( (prev, next) => {
const new_m = (next[0] || []).map( id => {
return next[1][id];
});
const old_m = (next[0] || []).map( id => {
return prev[1][id];
});
return prev[0] === next[0] && (JSON.stringify(new_m) === JSON.stringify(old_m))
})
.map( ([ids = [], modelBs]) => ids.map( id => modelBs[id]) );
};
//use the selector
this.store.let(getModelAModelBs(1)).subscribe( data => {
console.log(data)
})
But I don't know if this is the best approach.
I was struggling with the same issue and came up with a solution of wrappers.
Please take a look at the ngrx-entity-relationship library: https://www.npmjs.com/package/ngrx-entity-relationship
you can create selectors like that:
export const selectUserWithCompany = entityUser(
entityUserCompany(),
);
and then to use it with the store
this.store.select(selectUserWithCompany, 'userId');
to get
{
id: 'userId',
companyId: 'companyId',
company: {
id: 'companyId',
// ...,
},
// ...,
}

Categories

Resources