How do I map JSON data that is passed into a function? - javascript

Im trying to take JSON data and pass it into my 'HistoryChart' Component to try and map the dates and prices into two arrays so that I can present them on my chart. However, I keep getting undefined errors.
Here is the JSON Data:
{
"_id": 1,
"name": "",
"brand": "",
"image": "",
"sources": [],
"history": [
{
"_id": 3,
"price": "299.99",
"product": 1,
"date": "2021-07-01"
},
{
"_id": 4,
"price": "399.99",
"product": 1,
"date": "2021-07-08"
},
{
"_id": 5,
"price": "499.99",
"product": 1,
"date": "2021-07-15"
},
{
"_id": 6,
"price": "599.99",
"product": 1,
"date": "2021-07-22"
},
{
"_id": 7,
"price": "699.99",
"product": 1,
"date": "2021-07-29"
}
]
}
Here is my HistoryChart Component:
function HistoryChart({product}) {
var dates = product.history.map(function(e){ //<-- The Problem lies here where it says cannot map undefined.
return e.date;
});
var prices = product.history.map(function(e){
return e.price;
});
return (
<div>
<Line
data={{
labels: dates,
datasets: [{
label: `Average Price History (ID: ${product._id})`, //<-- This part works
backgroundColor:/* 'transparent' */ '#00ad0e',
borderColor: '#00ad0e',
data: prices,
}]
}}
width={100}
height={50}
options={{ maintainAspectRatio: true }}
/>
</div>
)
}
I am also using redux to get the Data:
const productDetails = useSelector(state => state.productDetails)
const {error, loading, product} = productDetails
And the data is passed into the HistoryChart Component like this:
<HistoryChart product={product}/>
Any Help would be Much appreciated, Thanks.

Sorry if this is not your principal problem, but same time when .map resulting in undefined the most simple adjust is verify if your array is undefined.
So in my projects i always check first if array is undefined, i will use your code to do a example
function HistoryChart({product}) {
if (product !== undefined){
var dates = product.history.map(function(e){
return e.date;
});
var prices = product.history.map(function(e){
return e.price;
});
}
Try this aproach and let me know if this work.

Cause of Error
As the data come from server, it take some time to load. and you get the undefine error because 1st time you want to access history of object product which is not yet loaded successfully.
Solution
const price = product && product.history.map(//do what you want)
use key values of object this way not cause any error because if product is not loaded it does'nt call map function and when product object loaded successfully it will call map function

Related

Remove duplicate items from the array retracted from api

I am building a Blog app and I am trying to get results but it is showing duplicate results, I am trying to remove the duplicate results from the array.
But the problem is there are two key and values in each dict inside array, One is unique and other can be same so I am trying to distinct based on same array, It worked But the other key and value pair (which is unique) is not attaching with the other pair.
response which is returning from db
[
{
"id": 2,
"name": "user_1"
},
{
"id": 3,
"name": "user_3"
},
{
"id": 4,
"name": "user_3"
}
]
App.js
function App() {
const [blogs, setBlogs] = useState([]);
axios.get("retract_blogs/").then((res) => {
// Here I also want to attach "id"
setBlogs({[...new Set(res.data.data.map(x => x.name))]})
}
return(
<div>
{
blogs.map((user) =>
<div>
{user.name}
// Here I wamt to show ID
// {user.id}
</div>
}
</div>
)
}
I want to add id with x.username, I also tried using
setBlogs({data:[...new Set(res.data.data.map(x => x.name, x.id))]})
But it showed
x is not defined
But I am trying to add both name and id, and remove duplicates based on name not id.
I have tried many times but it is still not working.
To keep the id of the last occurence you can create a Map of the array keyed by name and then convert back to an array using the iterator returned by Map.values(). This works by overwriting earlier entries in the Map with the same name.
const users = [{ "id": 2, "name": "user_1" }, { "id": 3, "name": "user_3" }, { "id": 4, "name": "user_3" }];
const result = [...new Map(users.map((user) => [user.name, user])).values()];
console.log(result);
// [ { id: 2, name: 'user_1' }, { id: 4, name: 'user_3' } ]
If you instead want to keep the id of the first occurence of a name you can use a slightly modified 'group by' grouping into an object by name (here in a reduce() call, but it could easily be done in a standard loop as well) before taking the Object.values. This works by only setting the accumulator[name] property if it doesn't already exist, here using logical nullish assignment (??=)
const users = [{ "id": 2, "name": "user_1" }, { "id": 3, "name": "user_3" }, { "id": 4, "name": "user_3" }];
const result = Object.values(users.reduce((a, c) => (a[c.name] ??= c, a), {}));
console.log(result);
// [ { id: 2, name: 'user_1' }, { id: 3, name: 'user_3' } ]

Issue with mapping Object of Arrays

I am trying to set up a block of code to prepare to setState, however, I'm running into an issue mapping a list in the render section as reactjs is telling me map is not a function. I don't think I'm setting this up correctly initially and it should be an array of objects instead of object arrays.
My goal is to set up a list. The names on the left side. The sum total of ondinResult and cmfResult on the right side. Below is the result I should expect:
This is how the data from the API is after calling the GET request:
"fileResults": {
"incFiles": [
{
"assetManagerId": 5,
"name": "BlackRock",
"odinResult": {
"total": 5,
"success": 2,
"error": 3
},
"cmfResult": {
"total": 0,
"success": 0,
"error": 0
}
},
{
"assetManagerId": 8,
"name": "Barings",
"odinResult": {
"total": 0,
"success": 0,
"error": 0
},
"cmfResult": {
"total": 10,
"success": 8,
"error": 2
}
},
{
"assetManagerId": 11,
"name": "AIM Derivatives",
"odinResult": {
"total": 6,
"success": 4,
"error": 2
},
"cmfResult": {
"total": 0,
"success": 0,
"error": 0
}
},
{
"assetManagerId": 11,
"name": "AIM Derivatives",
"odinResult": {
"total": 0,
"success": 0,
"error": 0
},
"cmfResult": {
"total": 8,
"success": 2,
"error": 6
}
}
],
"odinTotal": 11,
"cmfTotal": 18
},
My code block I'm currently setting up before setState:
//mapping odin and cmf results then adding the totals together
let odinTotal = response.data.fileResults.incFiles.map(item => item.odinResult.total)
let cmfTotal = response.data.fileResults.incFiles.map(item => item.cmfResult.total)
const legendData = {
labels: response.data.fileResults.incFiles.map(item => item.name),
totals: odinTotal.map(function (num, idx) {
return num + cmfTotal[idx]
})
}
My result is this from the above:
After deconstructing my state I tried to map it out in under render but get an error of: "Cannot read property 'map' of undefined."
<ul>
{legendData.labels.map(item => (
<li key={item}>{item}</li>
))}
</ul>
It sounds like you are fetching some data when the component mounts, so you need to likely provide some initial empty array value to legendData's labels array.
state = {
legendData: {
labels: [],
totals: [],
},
}
Then as long as your data loading logic also returns and updates state with an array your render logic will work.
Another option is to use a guard pattern on the mapping function to ensure the labels property exists and has a length property.
<ul>
{legendData && legendData.labels.length && legendData.labels.map(item => (
<li key={item}>{item}</li>
))}
</ul>
A react component in which you use map should always have a Intial state to empty array or empty object based on requirement.
check for the condition:
{legendData && legendData.labels.length ?
legendData.labels.map(item =>(
<li key={item}>{item}</li>
)) : null}

How does one filter json after type?

So, I have a json which looks a little bit like this:
{
"data": {
"user": {
"edge_followed_by": {
"count": 22,
"page_info": {
"has_next_page": true,
"end_cursor": "Base64"
},
"edges": [
{
"node": {
"id": "id",
"username": "Username",
"full_name": "played",
"profile_pic_url": "URL"
}
}
]
}
}
}
}
And I want to filter out the username. How do I do that?
You could retrieve it with a map function there
const dataSample = {
"data": {
"user": {
"edge_followed_by": {
"count": 22,
"page_info": {
"has_next_page": true,
"end_cursor": "Base64"
},
"edges": [
{
"node": {
"id": "id",
"username": "Username",
"full_name": "played",
"profile_pic_url": "URL"
}
}
]
}
}
}
}
const getUsernames = data => {
return data.data.user.edge_followed_by.edges.map(e => e.node.username)
}
console.log(getUsernames(dataSample))
:)
This can be a little tricky to understand from the question first of all.
My interpretation of this is you want to extract a username
"Filtering" also could mean you want to remove something from a collection that passes a condition (or test) of some kind.
For example: Removing all even numbers from an array
let x = [1, 2, 4, 5, 6];
let filtered = x.filter(value => value % 2 === 0);
Now, I've looked at your json, and I think the best point of targeting this is by getting the "edges" property and running it through an inbuilt function like map; that could be used to get usernames. The edges is an array as well.
data.user.edge_followed_by.edges.map(userObject => userObject.username)
That would effectively remove all usernames from the edges if your tech stack of choice was javascript.
I got this info from a post like: https://coderin90.com/blog/2019/map-js

How do I rename & delete multiple keys in an array?

I am trying to build a pie chart in react js which uses highcharts (https://api.highcharts.com/highcharts/) is accepting only the following format for pie chart data (or maybe I'm wrong): Sample Fiddle here: https://jsfiddle.net/react_user1/e9cbsrdL/1/
data: [
{name: 'abc', y: 10},
{name: 'def', y: 90}
]
The data I get from my API looks something like this:
const counts:[
{
"id": "all",
"type": "all",
"count": 1403
},
{
"id": "bad",
"type": "bad",
"count": 0
},
{
"id": "failed",
"category": false,
"type": "failed",
"count": 58
},
{
"id": "changed",
"category": true,
"type": "changed",
"count": 123
}
So I am trying to achieve three things here:
1. Remove the first {}, with the "id": "all"
2. Rename the key: "id" to name & "count" to y
3. Remove the keys: "type" & "category" & their data
Thanks for any help you could provide, even a partial answer that can help would be appreciated.
I think you can use Array.prototype.filter() and Array.prototype.map() combination.
With filter() you can remove the value what you don't need - in your case all - then with map() you can create a new structure for you array.
From the documentations - link mentioned above:
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.
Just like this:
const counts = [
{
"id": "all",
"type": "all",
"count": 1403
},
{
"id": "bad",
"type": "bad",
"count": 0
},
{
"id": "failed",
"category": false,
"type": "failed",
"count": 58
},
{
"id": "changed",
"category": true,
"type": "changed",
"count": 123
}
];
const result = counts.filter(f => f.id !== 'all')
.map(e => ({ name: e.id, y: e.count }));
console.log(result);
I hope this helps!
You can also provide data as an array of arrays:
series: [{
data: (() => counts.map(
item => [item.id, item.count]
))()
}]
Live demo: https://jsfiddle.net/BlackLabel/op4s13dm/
try this
renderarrayobjects = () => {
return this.state.arrayname.map((Arrayelement, Indexvalue) => {
return (
<View style={styles.btnColor}>
<Text style={styles.tagtext}>{Arrayelement}</Text>
<TouchableOpacity
Indexvalue={Indexvalue}
onPress={() => {
this.remove(Arrayelement);
}}>
<Image style={styles.editskill} source={deletarray} />
</TouchableOpacity>
</View>
);
}); };
The index value is the Index value.
this will render a list of Array items and we add an image that will be pressed to delete array the cross image will appear after every element of an array
removePeople(Arrayelement) {
var array = [...this.state.Arrayelement];
var index = array.indexOf(Arrayelement);
if (index !== -1) {
array.splice(index, 1);
this.setState({Arrayelement: array});
} }
this method will delete array objects.
Hope it helps .feel free for doubts

How to parse a JSON array string in JavaScript?

I have an JSON array like this
var filter_value_data = [{"Status":[{"name":"Open","id":"1"},{"name":"Pending","id":"2"},{"name":"Resolved","id":"3"},{"name":"Closed","id":"4"},{"name":"Evaluation","id":"5"}]},{"Payment Status":[{"name":"Paid","id":"10"},{"name":"UnPaid","id":"11"},{"name":"Part Paid","id":"12"}]},{"Priority":[{"name":"Low","id":"6"},{"name":"Medium","id":"7"},{"name":"High","id":"8"},{"name":"Urgent","id":"9"}]}]
I have tried filter_value_data["Status"] which is obviously wrong. How do I get the JSON elements for Status using the names like Status,Payment Status?
filter_value_data is an array (having []), so use filter_value_data[0].Status to get the first element-object with property "Status".
It is always good to format your code in order to see the hierarchy of the structures:
var filter_value_data = [
{
"Status": [
{
"name": "Open",
"id": "1"
}, {
"name": "Pending",
"id": "2"
}, ...
]
}, {
"Payment Status": [
{
"name": "Paid",
"id": "10"
}, ...
]
}, {
"Priority": [
{
"name": "Low",
"id": "6"
}, ...
]
}
];
With your current JSON you can't get the elements with the name alone.
You can get Status with filter_value_data[0]['Status'] and Payment status with filter_value_data[1]['Payment Status'].
This is because the keys are in seperate objects in the array.
In order to get them with filter_value_data['Status'] you need to change your JSON to
var filter_value_data = {
"Status":[
{"name":"Open","id":"1"},
{"name":"Pending","id":"2"},
{"name":"Resolved","id":"3"},
{"name":"Closed","id":"4"},
{"name":"Evaluation","id":"5"}
],
"Payment Status":[
{"name":"Paid","id":"10"},
{"name":"UnPaid","id":"11"},
{"name":"Part Paid","id":"12"}
],
"Priority":[
{"name":"Low","id":"6"},
{"name":"Medium","id":"7"},
{"name":"High","id":"8"},
{"name":"Urgent","id":"9"}
]
};
I wrote this on my phone so it's not as well-formatted as usual. I'll change it ASAP.
With your current JSON, created a result which might be helpful for you.
JS:
$.each(filter_value_data,function(ind,val){
var sta = val.Status; // Status Object get displayed
for(var i=0;i<sta.length;i++){
var idVal= sta[i].id;
var nameVal = sta[i].name;
Statusarray.push(idVal,nameVal);
console.log(Statusarray);
}
})
FiddleDemo
You can use below code, it will return status object
filter_value_data[0]['Status']
filter_value_data[0]['Payment Status']
to get Single value you use :
filter_value_data[0]['Status'][0]['name']

Categories