2

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

andres
  • 1,558
  • 7
  • 24
  • 62

2 Answers2

3

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

0stone0
  • 34,288
  • 4
  • 39
  • 64
  • Hey 0stone0, thank you for your help. Please see my update post. While this works great, there is still a problem occurring as the Carousel thinks this is one large child of graphs. – andres Mar 06 '21 at 19:19
  • 1
    Thank you so much, this solves it. I am having one small issue during renders. How can I create a conditional or wait for array_chuncks() to slice `symbolData` on initial render? Currently getting `TypeError: Cannot read property 'length' of undefined ` as an error as the data prop hasn't passed yet. – andres Mar 07 '21 at 04:44
  • Glad it worked! Im unable to reproduce the above mentioned bug, so unable to help you debug that. Maybe you could do something like `if (!SymbolData) return null;` to prevent calling `.length` if the `SymbolData` does not yet exist? Othwerise you can ask a new question regarding this issue! – 0stone0 Mar 07 '21 at 16:14
0

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={?}>

Abhishek Sharma
  • 2,485
  • 1
  • 21
  • 35