I have an array of images and I wanted to them to be in ascending order.
My problem is I want the first image to be on the <CardMedia/>
while the other remaining images to be put on <img>
. What will be the most ideal way to do this using the latest version of JS?
Codesandbox -> CLICK HERE
Code
export default function BasicCard() {
const orderImages = images.sort(function (a, b) {
return a.order - b.order;
});
return (
<Card>
<Stack spacing={1}>
<CardMedia
component="img"
image={orderImages?.[0]?.url}
sx={{
maxHeight: { xs: 100, sm: 100 },
objectFit: "cover"
}}
/>
<Grid container spacing={0.5}>
{orderImages?.map((image) => (
<Grid key={image.order} item xs={4}>
<img src={image.url} width="100%" />
</Grid>
))}
</Grid>
</Stack>
</Card>
);
}
Expected Output below
Card Media
{
order: 0,
url: "https://source.unsplash.com/user/c_v_r/1900x800"
},
Img src
{
order: 1,
url: "https://html.com/wp-content/uploads/flamingo.jpg"
},
{
order: 5,
url:
"https://res.cloudinary.com/demo/image/upload/if_ar_gt_3:4_and_w_gt_300_and_h_gt_200,c_crop,w_300,h_200/sample.jpg"
}
CodePudding user response:
It's a good idea to maintain immutability because it makes it easier to reason about your code:
const orderImages = images.sort(function (a, b) {
return a.order - b.order;
});
This function is actually changing the images
array. which is quite bad because it creates hard to find bugs. What's happening here is:
images.sort
changes theimages
array and passes the reference (check this thread for a good explanation on how JS treats Arrays) to yourorderImages
variableconst heroImage = orderImages.shift();
(in your CodeSandbox) is removing the first element from the array (which, remember, is theimages
array)
So once you get to render it it's already a mess. Plus, I'm not sure how CodeSandbox works but I think the application re-renders without reloading the images
array, so you'll be using the modified version in memory every time you save the file (without a full reload), which means the array will have 1 less element for every time orderImages.shift()
runs.
The way I'd do this safely would be something like this:
export default function BasicCard() {
// using the spread operator copies the array
// so you're not modifying the original array
const orderImages = [...images].sort(function (a, b) {
return a.order - b.order;
});
// This syntax extracts the 1st element of the array
// as well as the "rest" of it (with the 1st element removed)
// but if you check orderImages, it's still intact
const [first, ...rest] = orderImages;
return (
<Card>
<Stack spacing={1}>
<CardMedia
component="img"
image={first.url}
sx={{
maxHeight: { xs: 100, sm: 100 },
objectFit: "cover"
}}
/>
<Grid container spacing={0.5}>
{rest.map((image) => (
<Grid key={image.order} item xs={4}>
<img src={image.url} width="100%" />
</Grid>
))}
</Grid>
</Stack>
</Card>
);
}
CodePudding user response:
You can use Array destructuring to achieve that:
const [firstImage, ...otherImages] = orderImages;
firstImage
contains the first image --> Card MediaotherImages
contains an array of all the other images --> Image src