How to map an Array of children items for a Carousel?

Viewed 877

I'm trying to wrap a Carousel component around an array of mapped objects as children of the component. Currently I'm only able to have the mapping create 1 child of mapped objects.

The Carousel needs to be like so:

<Carousel>
    <div>1</div>
    <div>2</div>
    <div>3</div>
</Carousel>

but will not work properly on this one

<Carousel>
    <div>
        <div>1</div>
        <div>2</div>
        <div>3</div>
    </div>
</Carousel>

Please see the original reproducible code that has my carousel wrapped around 1 Child of mapped items: https://codesandbox.io/s/blissful-elion-993vy Note you will see that the Carousel works fine, but many of the Carousel properties are not working at all because it's wrapped around one child, such as animation and indicators prop.

I've tried doing this:

          <Carousel
            autoPlay={false}
            onClick={handleChangePage}
            next={loopNext}
            prev={loopPrev}
            NextIcon={<ArrowForwardIosRoundedIcon fontSize='large'/>}
            PrevIcon={<ArrowBackIosRoundedIcon fontSize='large'/>}
            navButtonsProps={{      
              style: {
                  backgroundColor: 'transparent',
                  color:"#447CF0"
              }
            }} 
            indicators={true}
            swipe={true}
            animation="slide"
          >
              {data[0]?.slice((page - 1) * itemsPerPage, page * itemsPerPage)
                .map((data, index) =>
                {
                  return (  
                    <Container key={index} maxWidth="lg" component="main">
                      <Grid container  key={index}>
                        <Grid item key={index} xs={4} md={4}>
                            <Card>
                            <CardHeader
                            title={<Chip label={data.symbol} />} 
                            subheader={data.adj_close}        
                            />      
                            <CardContent >
                              <MiniGraphs
                                historicalPrice={historicalPrice.filter(i => i.symbol === data.symbol)}
                                dateRange={date}
                              />            
                            </CardContent>
                            </Card>
                        </Grid>
                      </Grid>
                      </Container>
                    );
                })}
          </Carousel>

but the Carousel does not re-produce the expected result. It will only show 1 Child per slide , when I've set the number of 3 children per slide.

I think I have too slice the item array into slices of 3 items, and then map each slice to <Container> --> <Grid container> --> <Grid item/> --> ...

Currently stuck on how to accomplish that.

EDIT: I fixed the sandbox.

EDIT: The desired output is to have all graphs displayed properly as many children in arrays. As you can see in the picture below, only one child is filling up the Carousel per slide (I think because I need to explicitly map at an array of children?). Notice the indicators (grey circles) below the Carousel? They need to appear, if not then it's still one big child of graphs. enter image description here

2 Answers

Updated answer:

The carousel requires all the fields to be rendered on start.

To create multiple slides with 3 items on each slide, you should 'split' the data array into multiple sections, containing 3 items each.

For those items, you render a single <Container> with the 3 children inside like so:

const array_chunks = (array, chunk_size) => Array(Math.ceil(array.length / chunk_size)) .fill() .map((_, index) => index * chunk_size) .map((begin) => array.slice(begin, begin + chunk_size)); 
const chunks = array_chunks(SymbolData, 3);
<Carousel>
    {chunks.map((chuk) => {
        return (
            <Container>
                {chuk.map((c) => {
                    return (
                        <Grid item xs={4} md={4}>
                            <Card>
                                <CardHeader/>
                                <CardContent>
                                </CardContent>
                            </Card>
                        </Grid>
                    );
                })}
            </Container>
        );
    })}
</Carousel>

Note:

  • I've used the following Stack Answer to split the data array into chunks of 3:

    Split array into chunks

  • The <container> does not create a row, it's shown in a column. I guess you should be able to fix this, I'm not that familiar with material-ui

Sandbox


Original answer:

You're rendering a <container> for each map iteration.

Move the map inside the <container> so you can render multiple 'cells' in the single <container> like so:

<Container  maxWidth="lg" component="main">
    <Grid container>
        {SymbolData?.slice((page - 1) * itemsPerPage, page * itemsPerPage).map(
            (data, index) => {
                return (
                    <Grid item key={index} xs={4} md={4}>
                        <Card>
                            ...
                        </Card>
                    </Grid>
                );
            }
        )}
    </Grid>
</Container>

Updated CodesandBox

As per my understanding of the problem statement, there are two possible things out of which you want to achieve one.

First One: If you want to show all the three graphs in a single slide, you should move your symbolData map inside the <Grid container> just like the above solution and this CodeSandbox Since you are already slicing with page numbers, you will see n different slides with 3 graphs per slide based on the number of pages.

Second One (unlikely) : You might want to show the graph in full width of the slide. For that you need to use xs={12} md={12} in <Grid item key={index} xs={?} md={?}>

Related