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>
Related
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.
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>
);
I have a list of airplanes departing or arriving at the airport and i also had a search filter where i enter the time of arrival or departure and filtering of the airplanes. I do this using the actual property of my API. But I needed to change my search. Now I need to search by flight number - the planeTypeID.code property of my API. But when I changed it, stopped showing a list of airplanes. What is my mistake and how to fix it?
I just instead actual everywhere wrote ["planeTypeID.code"] and delete method:
.split("-").reverse().join("-")
OLD version:
small part airplane.js(reducer)
case "RUN_FILTER":
var newData = state.data[action.shift || state.shift].filter(x => {
return (
x.actual &&
x.actual.includes(
state.day
.split("-")
.reverse()
.join("-")
)
);
});
case "LOAD_DATA_END":
var newData = action.payload.data[state.shift].filter(x => {
return (
x.actual &&
x.actual.includes(
action.payload.day
.split("-")
.reverse()
.join("-")
)
);
});
small part app.js(main component)
export function searchFilter(search, data) {
return data.filter(n => n.actual.toLowerCase().includes(search));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
NEW version:
small part airplane.js(reducer)
case "RUN_FILTER":
var newData = state.data[action.shift || state.shift].filter(x => {
return (
x["planeTypeID.code"] && // Сhange
x["planeTypeID.code"].includes( // Сhange
state.day
// delete
)
);
});
return Object.assign({}, state, {
case "LOAD_DATA_END":
var newData = action.payload.data[state.shift].filter(x => {
return (
x["planeTypeID.code"] && // Сhange
x["planeTypeID.code"].includes( // Сhange
action.payload.day
// delete
)
);
});
small part app.js(main component)
export function searchFilter(search, data) {
return data.filter(n => n["planeTypeID.code"].toLowerCase().includes(search)); // Сhange
}
All project code in sandbox:
https://codesandbox.io/s/redux-ant-design-filter-table-column-with-slider-jj6mu
An example value of x["planeTypeID.code"] is "B734", of state.day "23-08-2019" => those are 2 different fields => you will get an empty array when you filter by x["planeTypeID.code"].includes(state.day) ¯\_(ツ)_/¯
After debugging via comments, the most likely solution is:
x["planeTypeID.code"].toLowerCase().includes(action.search || state.search)
I recommend to Get Started with Debugging JavaScript as a generic first step to questions that start with:
Where did I make the mistake...
...before posting to Stack Overflow.
I have an array, with custom Emoji objects, which I'm mapping through to display in my JSX code.
I have handler, where a user can add an emoji, and will increment a counter, each time it is selected.
addEmoji = (newEmoji) =>{
// mark if new emoji is already in the array or not
let containsNewEmoji = false;
// recreate emojis array
let newEmojis = this.state.emojis.map(emoji => {
// if emoji already there, simply increment count
if (emoji.id === newEmoji.id) {
containsNewEmoji = true;
return {
...newEmoji,
...emoji,
count: emoji.count + 1,
};
}
// otherwise return a copy of previos emoji
return {
...emoji
};
});
I imported the Emoji component, from the emoji-mart node module, and mapping the:
<div className="emoji">
{this.state.emojis &&
this.state.emojis.map( (emoji, index) =>{
return(
<Emoji key={index} onClick={this.addEmoji} tooltip={true}
emoji={{id: emoji.id, skin: 1}} size={25} />
)
})
}
</div>
how can I display the counter variable, next to the Emoji, to see how many times it has been displayed?
You can a create a component called EmojiCount to you'll pass emoji and count as props
const EmojiCount = (props) => {
return (
<Emoji {...props.emoji} />
<div>{props.count}</div>
);
}