I have a list of objects that I am mapping over to display the news on a page. The problem is the date comes to me in Unix timestamp instead of correct date format. I am trying to convert it, but every method I can find is only converting 1 item from the list.
I've tried 2 different ways so far
1st way:
return (
<Container>
{records &&
records.map((record, index) => {
const update = new Date(records.datetime * 1000).toLocaleDateString('en-US');
return (
<span>{record.update}</span>
))};
</Container>
);
2nd way
import timestamp from 'unix-timestamp';
<span>{timestamp.toDate(record.datetime)}</span>
it seems that you don't use update. Also, you are referencing records instead of record inside your loop.
Try this:
return (
<Container>
{records &&
records.map((record, index) => {
const update = new Date(record.datetime * 1000).toLocaleDateString('en-US');
return (
<span>{update}</span>
))};
</Container>
);
Related
I have some json data:
{
"shops" :
[
{
"type" : "Blacksmith/Armoury",
"items_light_armour" :
[
"Light Armour",
{
"id": 1,
"item" : "Padded Armour",
"low_price": 15,
"med_price": 20,
"high_price": 30,
"available": true,
"limited": false,
"weight": 8,
"blurb": "AC11. Made of quilted layers of cloth and batting."
},
//...
//three other objects, as array elements, with a similar set of key/value pairs
The first element (inside the items_light_armour array) is just a string to denote what category each data set is.
What I want to do, is display every single object (apart from its ID and blurb) in a table I have. The table generates new rows for every item mapped through.
The problem I have is that it's not mapping out the data as intended.
Here's a picture of what the table looks like at when it first loads:
So the data does map to the table, but only the first item in each array of objects. Im honestly unsure of how to get all of the data for each category.
Specifically, each category should list all of its items, then a new category would open up, list all of its entries like the first and so on until the end of the array is reached, instead of one from each as displayed above.
Here's how I get my data from the JSON file (above my return block in the component):
//get the json data
const jsonData = require("../Reference Files/Json Files/shops.json");
Then, I convert it to a const
const objInnerValues = Object.values(jsonData.shops[0])
Then, in the return block of my component, here's how I 'fill' the table rows.
EDIT: This is the latest code, following advice from #John:
//...
{
<>
objInnerValues.map((things, outerIndex) => (
{outerIndex === 0 ? console.log("outerIndex WAS 0"):
<TableRow key= {outerIndex} onClick={() => BarkItemBlurb(outerIndex)}>
{Object.values(things).map((eachThing, innerIndex) => (
{innerIndex == 0 ? console.log("innerIndex or outerIndex was 0"):
<>
<SuperTD key={innerIndex}>{eachThing.item}</SuperTD>
<SuperTD key={innerIndex+1}>{eachThing.weight}lbs</SuperTD>
<SuperTD key={innerIndex+2}>{eachThing.low_price}gp</SuperTD>
<SuperTD key={innerIndex+3}>{eachThing.med_price}gp</SuperTD>
<SuperTD key={innerIndex+4}>{eachThing.high_price}gp</SuperTD>
</>
})
</TableRow>
})
</>
}
//...
I'm using styled-components, hence the weird html tag names.
Any advice would be greatly appreciated.
This is probably want you want. When you get thing, you map that and you don't need to index it because eachThing is the actual object.
{
objInnerValues.map((things, i) => (
{things.map((eachThing) => (
<TableRow key= {i} onClick={() => BarkItemBlurb(i)}>
<SuperTD>{eachThing.item}</SuperTD>
<SuperTD>{eachThing.weight}lbs</SuperTD>
<SuperTD>{eachThing.low_price}gp</SuperTD>
<SuperTD>{eachThing.med_price}gp</SuperTD>
<SuperTD>{eachThing.high_price}gp</SuperTD>
</TableRow>
)}
))}
Given I haven't ran this due to lack of working code; I may have the wrong number of brackets/closing brackets and may have it in the wrong place but overall it should guide you to a solution.
Thanks to #John for the assist.
I overcomplicated my design. My JSON file contained arrays and objects, making it awkward to navigate.
After restructuring it to contain only arrays, it was a lot easier.
Also, as for the actual problem, I was shown that I needed to add another map function inside my original one to make it spit the data out the right way.
//...
Object.values(thing).map((innerThing, innerIndex) => (
<>
{console.log("\nouter/inner: "+outerIndex +", " +innerIndex)}
{console.log("\nData: \n\t"+innerThing[2] +"\n\t" +innerThing[8] + "\n\t" +innerThing[3]+"\n\t" + innerThing[4]+"\n\t"+innerThing[5])}
<TableRow key = {thing[0].toString()}>
<SuperTD>{innerThing[2]}</SuperTD>
<SuperTD>{innerThing[8]}lbs</SuperTD>
<SuperTD>{innerThing[3]}gp</SuperTD>
<SuperTD>{innerThing[4]}gp</SuperTD>
<SuperTD>{innerThing[5]}gp</SuperTD>
</TableRow>
</>
//...
Now, with the mapping sorted, this is the result:
I have a React component that consumes the value objects - which gives us access to an array, but currently, using the map function is going to return an array of labels/ assistants as opposed to just one string value. Can anyone help out I would best refactor this code to reflect this change? The current implementation does return the correct values, but I'm just not sure its the right use of map.
const FirstRepeatAttributeLabelAssistant = ({ objects, className }: Props) => {
if (objects.length === 0) {
return null;
}
let label = objects[0].attributeCollection.questions.map((question) => {
return question._contributions.label;
});
let assistant = objects[0].attributeCollection.questions.map((question) => {
return question._contributions.assistant;
});
return (
<StyledGroup as={Row}>
<StyledLabelWrapper>{label}</StyledLabelWrapper>
<Column size={12} />
<Column>
<StyledAssistantWrapper>{assistant}</StyledAssistantWrapper>
</Column>
</StyledGroup>
);
};
This is the array in question:
So, I really just want to assign my values label & assistant to those in this array.
Current output when I console.log(labely);:
I am working with bigger arrays in React, and want the following display like this: image/name image/name image/name. I have the following the code but I don't know how I can map over the images array to so it shows it's image. Thank you
function showProtocolsNames() {
if (supportedVaults) {
let arr = supportedVaults
.map((item) => item.protocolName)
.filter((item, index, arr) => {
return arr.indexOf(item) == index;
});
let arrImages = supportedVaults
.map((item) => item.protocolKey)
.filter((item, index, arr) => {
return arr.indexOf(item) == index;
});
let protocolsName = [...new Set(arr)];
let protocolsImages = [...new Set(arrImages)];
console.log(protocolsName, protocolsImages);
return protocolsName.map((vault) => {
return (
<>
{' '}
<img
src={getVaultIcon(vault)}
width="42px"
height="42px"
style={{
marginRight: '12px',
}}
/>
<p className="vaults-protocol">{vault}</p>
</>
);
});
}
return null;
}
Solved: By creating an array of the images and names together and just mapping over it like DBS suggested in comments.
I believe there is a much simpler solution to your problem than your current approach. For example, you could use the supportedVaults data immediately while mapping the image/name components, like this:
function showProtocolsNames() {
// added check to ensure there is data inside supportedVaults
if (supportedVaults.length) {
// removed the two mapped arrays
// added index which is generated by map function
return protocolsName.map((vault, index) => {
// added div instead of <> in order to include a key, which is required in a map function
return (
<div key={`${index}-${vault?.protocolKey}`}>
{" "}
<img
src={getVaultIcon(vault?.protocolKey)} // here we pass protocolKey to the getVaultIcon function
width="42px"
height="42px"
style={{
marginRight: "12px",
}}
/>
{/* here we add protocolName inside the paragraph */}
<p className="vaults-protocol">{vault?.protocolName}</p>
</div>
);
});
}
return null;
}
This logic above is based on your description of the issue, assuming protocolKey is what you need to pass to get the vault icon in getVaultIcon function and protocolName is the value you need to show as the name. If my perception is wrong, please edit your question to reflect more info on what exact data you need to get from the supportedVaults array, or what format supportedVaults has.
Currently I'm working on small React project where I'm using data provided by a flight information API. Everything is working according to plan so far. I can display all array items in a list. Now I'm trying to implement a feature that displays date on a separate row in the list. I only want to display a date one time for one or more items with the same date.
Down below in the condition I'm using the variable displayDate. Basically just to be able to turn the date on/off for the moment and to test some logic. What I'm trying to figure now is what logic I need to be able to evaluate the if statement to either true or false. There has to be some sort of comparison between the current date and the next date in the array.
Each object in the array has a property called scheduleDate formatted as "2020-07-06".
Any ideas how I can solve this?
<Flights>
{resolvedData &&
resolvedData.flights
.filter((item) => item.flightName === item.mainFlight)
.map((item, index) => {
if (displayDate) {
return (
<React.Fragment key={item.id}>
<Date date={item.scheduleDate} />
<Flight flight={item} />
</React.Fragment>
);
} else {
return <Flight key={item.id} flight={item} />;
}
})}
</Flights>
Check if the scheduleDate is different than the previous
const renderTable = () => {
let currentDate = null;
return data.map((item, index) => {
if (item.scheduleDate !== currentDate) {
currentDate = item.scheduleDate;
return (
<>
<Date/>
<Flight/>
</>
);
} else {
return <Flight/>;
}
});
};
<Flights>{renderTable()}</Flights>
I have a map loop that returns a list of values eg 0 - 100. The problem is that this will return the whole list. I want to only return a specific number of values. eg (11-20). What would be the best way of implementing this?
The current code is
const all = this.props.memories.map((value, index) => {
return (
<div>
{value}
</div>
)
})
Use .slice() as this.props.memories.slice(11, 20).map...
Slice ..Use it when you do not want to alter the original contents, instead a shallow copy of that for local change and usage.
this.props.memories.slice(11,20).map((value, index) => {
return (
<div>{value}</div>
)
})