timbo245
timbo245

Reputation: 194

Map is returning the items of an array multiple times

I have an array of object which contains images:

import React, { Fragment } from "react"
import { useStaticQuery, graphql } from "gatsby"

import Button from "@material-ui/core/Button"
import Card from "@material-ui/core/Card"
import CardActions from "@material-ui/core/CardActions"
import CardContent from "@material-ui/core/CardContent"
import CardMedia from "@material-ui/core/CardMedia"
import { CardActionArea, GridList } from "@material-ui/core"
import CssBaseline from "@material-ui/core/CssBaseline"
import Grid from "@material-ui/core/Grid"
import Toolbar from "@material-ui/core/Toolbar"
import Typography from "@material-ui/core/Typography"
import Container from "@material-ui/core/Container"
import Link from "@material-ui/core/Link"

import homePageStyles from "../ui/styles/homePageStyles"

import mobile from "../../images/mobileApps.jpeg"
import coporation from "../../images/coporations.png"
import statute from "../../images/gavel.png"
import policy from "../../images/policies.png"

export default function HeroBlock() {
  const classes = homePageStyles()

  const data = useStaticQuery(graphql`
    query getCardCategoriesAndCounts {
      allStrapiCategory {
        edges {
          node {
            category
            strapiId
          }
        }
      }
      allStrapiMobileApplication {
        totalCount
      }
      allStrapiCorporation {
        totalCount
      }
      allStrapiStatutoryLaw {
        totalCount
      }
      allStrapiPolicyIssue {
        totalCount
      }
    }
  `)

  const categories = data.allStrapiCategory.edges

  const categoryImages = [
    { cImg: mobile },
    { cImg: coporation },
    { cImg: statute },
    { cImg: policy },
  ]

  console.log(categoryImages)

  const catImage = categoryImages.map(categoryImage => {
    return (
      <Fragment>
        <CardMedia
          image={categoryImage.cImg}
          className={classes.images}
        ></CardMedia>
      </Fragment>
    )
  })

  const cards = (
    <Fragment>
      {categories.map(c => (
        <Card style={{ width: "15.625rem", wordWrap: "break-word" }}>
          <div>{catImage}</div>
          <CardActionArea>
            <CardContent>
              <Typography variant={"h6"}>
                {c.node.category.toUpperCase().replace(/_/g, " ")}
              </Typography>
              <Fragment>
                {c.node.category === "Mobile_Apps" ? (
                  <Typography variant="paragraph">
                    {`There are currently ${data.allStrapiMobileApplication.totalCount} mobile applications.`}
                  </Typography>
                ) : c.node.category === "Corporations" ? (
                  <Typography variant="paragraph">
                    {`There are currently ${data.allStrapiCorporation.totalCount} coporations.`}
                  </Typography>
                ) : c.node.category === "Statutes" ? (
                  <Typography variant="paragraph">
                    {`There are currently ${data.allStrapiStatutoryLaw.totalCount} statutory laws.`}
                  </Typography>
                ) : c.node.category === "Policy_Issues" ? (
                  <Typography variant="paragraph">
                    {`There are currently ${data.allStrapiPolicyIssue.totalCount} policy issues.`}
                  </Typography>
                ) : (
                  <div></div>
                )}
              </Fragment>
            </CardContent>
          </CardActionArea>
        </Card>
      ))}
    </Fragment>
  )

  return (
    <React.Fragment>
      <CssBaseline />
      <main>
        <div className={classes.heroContent}>
          <Grid container>
            <Grid item classes={{ root: classes.heroColumn }}>
              <Grid container>
                <Grid
                  item
                  container
                  direction="column"
                  classes={{ root: classes.hero }}
                >
                  <Typography component="h1" variant="h2" align="center">
                    MIKE <br /> The Mobile Information Knowledge Ecosystem
                  </Typography>
                  <Typography variant="h5" align="center" paragraph>
                    <strong>
                      <em>The</em>{" "}
                    </strong>
                    central repository for how to extract data from a mobile
                    device, extract data from a mobile application, what data
                    the mobile app provider retains, and the specific laws
                    pertaining to accessing that data.
                  </Typography>
                </Grid>
              </Grid>
            </Grid>
          </Grid>
        </div>
        <Grid Container>
          <Grid item container justifyContent="space-evenly">
            {cards}
          </Grid>
        </Grid>
      </main>
    </React.Fragment>
  )
}

Updated with the entire code base. There is multiple map statements. If that is the issue how do you map multiple arrays inside React? Does that require using some sort of data store? It is returning each one of the images 4 times, rather than each images per card. enter image description here

Upvotes: 3

Views: 2352

Answers (2)

Drew Reese
Drew Reese

Reputation: 202608

You generate an array of card media components, and then render this within another loop, so this is why you see the 4 category images repeated for each category mapped later.

const catImage = categoryImages.map(categoryImage => { // array
  return (
    <Fragment>
      <CardMedia
        image={categoryImage.cImg}
        className={classes.images}
      ></CardMedia>
    </Fragment>
  )
})

const cards = (
  <Fragment>
    {categories.map(c => (
      <Card style={{ width: "15.625rem", wordWrap: "break-word" }}>
        <div>{catImage}</div> // <-- render array of images here!!
        <CardActionArea>
          ...

Assuming the categoryImages and categories arrays have the same length and sorted order, then you can render the card media component directly in the mapping and use the current index to access the correct image from the categoryImages array.

const cards = (
  <Fragment>
    {categories.map((c, index) => ( // <-- use current index
      <Card style={{ width: "15.625rem", wordWrap: "break-word" }}>
        <CardMedia
          image={categoryImages[index].cImg} // <-- access by index
          className={classes.images}
        />
        <CardActionArea>
          ...

Upvotes: 1

Cardoso
Cardoso

Reputation: 1088

Array.map returns array. So catImage is an array that contains components.
You can use each CardMedia component by indicating index number.

catImage[index]

catImage[0] is the first card. So you can update your code like below:

const cards = (           // <==== line 74
  <Fragment>
    {categories.map((c, index) => (
      <Card style={{ width: "15.625rem", wordWrap: "break-word" }}>
        <div>{catImage[index]}</div>

I hope my answer will be solve your problem.
Thanks.

Upvotes: 0

Related Questions