brainhubeu / react-carousel

A pure extendable React carousel, powered by Brainhub (craftsmen who ❤️ JS)
https://brainhub.eu/
MIT License
1.08k stars 164 forks source link

Recalculate Slide Width When Container Width Changes #160

Closed leclaeli closed 4 years ago

leclaeli commented 5 years ago

Issuehunt badges

Is your feature request related to a problem? Please describe. If the container element changes width the slider and controls respond, but the slide width and height remains the same. This cuts off images when reducing the width and when increasing the width you see multiple slides at a time.

Describe the solution you'd like It would be great if there was a way to recalculate the size of the slides via the api.

Describe alternatives you've considered I wondered if there was a React way to force the carousel to re-render that would trigger the calculations again, but I was unable to come up with a solution.

Additional context I'm using this in the WordPress Gutenberg editor to create a custom slider block. In Gutenberg there are alignment options (full width, wide, default, etc...) that allow you to change the width of your block/content and I'd like to have the slider update when the alignment is changed without having to reload the page.


IssueHunt Summary #### [bunysae bunysae](https://issuehunt.io/u/bunysae) has been rewarded. ### Backers (Total: $22.00) - [piotr-s-brainhub piotr-s-brainhub](https://issuehunt.io/u/piotr-s-brainhub) ($22.00) ### Submitted pull Requests - [#476 Using react-resize-observer to observe carousel width](https://issuehunt.io/r/brainhubeu/react-carousel/pull/476) --- ### Tips - Checkout the [Issuehunt explorer](https://issuehunt.io/r/brainhubeu/react-carousel/) to discover more funded issues. - Need some help from other developers? [Add your repositories](https://issuehunt.io/r/new) on IssueHunt to raise funds.
piotr-s-brainhub commented 5 years ago

have you tried this.setState(this.state)?

leclaeli commented 4 years ago

@piotr-s-brainhub I tried setting this.setState(this.state), but didn't have any luck getting that to do anything. Interestingly enough I nested the <Carousel> inside a functional component and that fixed the resizing issue. However, the slide animations stopped working so it would just jump from slide to slide with no effect. I tried, but couldn't make any sense out of it, but I'm a React newbie so I could be missing something.

piotr-s-brainhub commented 4 years ago

so could you provide:

leclaeli commented 4 years ago

Default: Carousel component inside return. This scrolls with animation, but doesn't resize correctly.

<div className={ classnames( 'uwm-p-slider', { 'uwm-p-slider--nav-outside': navOutside } ) } ref={ sliderWrapper }>
    <Carousel
        arrows
        centered
        infinite
        value={ slideValue }
        onChange={ updateSlideValue }
        { ...( ( autoPlay && ! isSelected )  && { autoPlay: 5000 } ) }
        dots
        { ...( cardSlider && { slidesPerPage: 3 } ) }
        { ...( cardSlider && { slidesPerScroll: 3 } ) }
    >
        {slides.map( (slide, index) =>
            <>
                { slide.id ? (
                    <div key={slide.id} className="uwm-slide">
                        <figure className={ (slide.caption && displayCaption) ? 'wp-caption' : ''}>
                            <img src={slide.url} alt={ slide.alt } title={ slide.alt } />
                            { (slide.caption && displayCaption) &&
                                <figcaption className="img-caption">
                                    { slide.caption }
                                </figcaption>
                            }
                        </figure>
                    </div>
                ) : (
                    <MediaPlaceholder 
                        icon="format-image"
                        onSelect={ (mediaProps) => onSelectImage(mediaProps, index) }
                        onSelectURL={ onSelectURL }
                        onError={ onUploadError }
                        accept="image/*"
                        allowedTypes={['image']}
                    />
                )}
            </>
        )}
    </Carousel>
</div>

Functional Component: This resizes correctly, but doesn't animate on scroll.

<div className={ classnames( 'uwm-p-slider', { 'uwm-p-slider--nav-outside': navOutside } ) } ref={ sliderWrapper }>
    <MyCarousel
        slideIndex={ slideIndex }
        slideValue={ slideValue }
        onChange={ updateSlideValue }
    />
</div>

and <MyCarousel>

 const MyCarousel = (props) => {
    const [sliderWidth, setSliderWidth] = useState(580);

    useEffect(() => {
        if (! cardSlider)
            setSliderWidth(sliderWrapper.current.offsetWidth)
    });

    return (
        <Carousel
            value={ props.slideValue }
            arrows
            infinite
            onChange={ props.onChange }
            { ...( ( autoPlay && ! isSelected )  && { autoPlay: 5000 } ) }
            dots
            { ...( cardSlider && { slidesPerPage: 3 } ) }
            { ...( cardSlider && { slidesPerScroll: 3 } ) }
            { ...( sliderWidth && { itemWidth: sliderWidth } ) }
            centered
        >
            {slides.map( (slide, index) =>
                <>
                    { slide.id ? (
                        <div key={slide.id} className="uwm-slide">
                            <figure className={ (slide.caption && displayCaption) ? 'wp-caption' : ''}>
                                <img src={slide.url} alt={ slide.alt } title={ slide.alt } />
                                { (slide.caption && displayCaption) &&
                                    <figcaption className="img-caption">
                                        { slide.caption }
                                    </figcaption>
                                }
                            </figure>
                        </div>
                    ) : (
                        <MediaPlaceholder 
                            icon="format-image"
                            onSelect={ (mediaProps) => onSelectImage(mediaProps, index) }
                            onSelectURL={ onSelectURL }
                            onError={ onUploadError }
                            accept="image/*"
                            allowedTypes={['image']}
                        />
                    )}
                </>
            )}
        </Carousel>
    )
}
piotr-s-brainhub commented 4 years ago

Thanks @leclaeli

issuehunt-oss[bot] commented 4 years ago

@piotr-s-brainhub has funded $5.00 to this issue.


piotr-s-brainhub commented 4 years ago

@leclaeli

Can I ask you to fill in this form https://docs.google.com/forms/d/1tfRs1Io49tJBwz-06aDnz8hrJ3WySJTi45y4k6hHGaQ ?

piotr-s-brainhub commented 4 years ago

@leclaeli

are you able to write a scenario with an example code possible to paste in the docs/demo?

issuehunt-oss[bot] commented 4 years ago

@piotr-s-brainhub has funded $15.00 to this issue.


sinchang commented 4 years ago

I found a package https://github.com/maslianok/react-resize-detector can help to resolve this issue.

simple code:

<div
          className={classnames('BrainhubCarousel', this.getProp('className'), isRTL ? 'BrainhubCarousel--isRTL' : '')}
          ref={el => this.node = el}
        >
          <ReactResizeDetector handleWidth onResize={this.onResize} />
          {this.renderArrowLeft()}
          {this.renderCarouselItems()}
          {this.renderArrowRight()}
        </div>
issuehunt-oss[bot] commented 4 years ago

@piotr-s-brainhub has funded $1.00 to this issue.


issuehunt-oss[bot] commented 4 years ago

@piotr-s-brainhub has funded $1.00 to this issue.


piotr-s-brainhub commented 4 years ago

@sinchang

You're welcome to open a PR with your solution.

piotr-s-brainhub commented 4 years ago

@sinchang

You can also like this issue (👍) so more 👍it has, it's more likely to be finished in the nearest time.

issuehunt-oss[bot] commented 4 years ago

@piotr-s-brainhub has rewarded $19.80 to @bunysae. See it on IssueHunt