maxmarinich / react-alice-carousel

React responsive component for building content galleries, content rotators and any React carousels
MIT License
843 stars 92 forks source link

Custom arrows - unable to use methods #161

Closed tiagomota79 closed 3 years ago

tiagomota79 commented 3 years ago

This issue has been mentioned before, but I was unable to get it working - the examples linked in the closed issues doesn't lead to the right place.

I'm trying to set custom arrows, but can't access the slidePrev and slideNext methods. Trying to use activeIndex works but I loose the smooth animation - see video below, showing default arrows vs custom buttons with activeIndex.

https://user-images.githubusercontent.com/45611789/104020650-88103680-518b-11eb-9b2e-07016d0a0399.mp4

Neither ref nor props are working for me - maybe because I'm using Typescript? The code below gets custom buttons to work, but without the animation.

What am I missing?

import React, { useRef, useState } from 'react';
import AliceCarousel from 'react-alice-carousel';
import 'react-alice-carousel/lib/alice-carousel.css';
import styled from 'styled-components';
import {
    // Typography,
    // IconButton,
    Card,
    CardHeader,
    // CardContent,
    // CardActionArea,
    // DialogActions,
    // DialogContent,
    // Box,
    // ExtendButtonBase,
    // IconButtonTypeMap,
} from '@material-ui/core';

import { useTranslation } from 'src/utils/i18n';

const StyledCard = styled(Card)`
    margin-bottom: 1rem;

    .MuiCardHeader-title {
        font-weight: bold;
    }

    .MuiCardContent-root:last-child {
        padding-bottom: 1rem;
    }
`;

const StoryCard = styled.div`
    height: 140px;
    width: 85px;
    overflow: hidden;
    text-overflow: ellipsis;
`;

const StoryImage = styled.div`
    display: grid;
    place-items: center;
    height: 115px;
    width: 100%;
    background-position: 50%;
    background-size: cover;
    text-align: center;
    border-radius: 2px;
`;

type Props = {};

const StoriesCard: React.FC<Props> = () => {
    const { t } = useTranslation(['common', 'news']);
    const [activeIndex, setActiveIndex] = useState<number>(0);

    // Mock data to test carousel
    const data = [
        {
            id: 1,
            image: 'http://dummyimage.com/1436x949.jpg/cc0000/ffffff',
            floatingText: 'eleifend',
            createdAt: '2020-07-09 12:16:32',
            updatedAt: '2020-04-17 02:35:55',
            userId: 'bf7c3632-6344-4187-b65a-b9049c69bd2f',
            userName: 'Nata Delph',
            adId: 'bb0bca9c-4a48-49ab-a44c-204ad9b3858e',
        },
        {
            id: 2,
            image: 'http://dummyimage.com/1233x694.jpg/5fa2dd/ffffff',
            floatingText: undefined,
            createdAt: '2020-06-18 11:42:47',
            updatedAt: '2020-08-05 21:17:02',
            userId: 'bc380daa-fa77-4832-9d6e-0a487b74ca5d',
            userName: 'Melodie Nunns',
            adId: '6cc2a33d-830b-4c78-9c92-35330cfad1d2',
        },
        {
            id: 3,
            image: 'http://dummyimage.com/1604x823.jpg/5fa2dd/ffffff',
            floatingText: undefined,
            createdAt: '2020-07-20 00:40:20',
            updatedAt: '2020-02-23 16:52:16',
            userId: '0dd39895-4298-43c7-91b2-e1e65ef8468e',
            userName: 'Evelina Bertrand',
            adId: '1c12a656-3ad7-4e3c-ab1c-f8c880ca901f',
        },
        {
            id: 4,
            image: 'http://dummyimage.com/905x907.jpg/dddddd/000000',
            floatingText: 'libero',
            createdAt: '2020-09-04 14:39:12',
            updatedAt: '2020-05-15 04:01:21',
            userId: '097873f2-5610-47d9-9aa2-f3e34037c768',
            userName: 'Consolata Szymon',
            adId: 'f7f66b94-d24e-48cd-9917-6eaa254c5dce',
        },
        {
            id: 5,
            image: 'http://dummyimage.com/1285x811.jpg/dddddd/000000',
            floatingText: 'erat vestibulum sed',
            createdAt: '2020-06-14 17:31:00',
            updatedAt: '2020-03-07 21:05:34',
            userId: 'ca5ce40b-0b5a-4488-af00-7494d12a8529',
            userName: 'Shalom Sandey',
            adId: '4ee34d34-5ef0-4b44-a133-3cde1a8284d2',
        },
        {
            id: 6,
            image: 'http://dummyimage.com/1514x738.jpg/dddddd/000000',
            floatingText: 'phasellus',
            createdAt: '2020-12-30 03:07:04',
            updatedAt: '2020-07-18 00:38:59',
            userId: '61fe637b-0031-4d0d-9fe9-011f8c02f7c3',
            userName: 'Ephraim Yakhin',
            adId: 'a53bd4c3-84ad-4997-81ea-0a9bf9e00189',
        },
        {
            id: 7,
            image: 'http://dummyimage.com/1339x786.jpg/5fa2dd/ffffff',
            floatingText: 'donec ut',
            createdAt: '2021-01-04 14:36:16',
            updatedAt: '2020-06-09 01:58:56',
            userId: '9e4055fb-4225-4bd4-b6ef-c3b7a22bb2e2',
            userName: 'Inge Sibbet',
            adId: '6de15034-3b60-4ab9-8ff7-5848912338a3',
        },
        {
            id: 8,
            image: 'http://dummyimage.com/1792x937.jpg/ff4444/ffffff',
            floatingText: 'eu felis fusce',
            createdAt: '2020-12-17 16:51:15',
            updatedAt: '2021-01-04 15:16:32',
            userId: 'b21c454d-412b-4c6f-ae11-c552c2175bcd',
            userName: 'Brad Scapens',
            adId: '3cac0f0c-20a0-4341-9031-3f8f3bfb7f0a',
        },
        {
            id: 9,
            image: 'http://dummyimage.com/955x932.jpg/ff4444/ffffff',
            floatingText: 'vitae ipsum aliquam',
            createdAt: '2020-05-17 07:13:30',
            updatedAt: '2020-06-06 22:12:22',
            userId: 'b1fc3d77-283a-42f3-b530-9df013d9c950',
            userName: 'Garreth Clymo',
            adId: '45128329-c07a-4678-8f96-8a94c2826d08',
        },
        {
            id: 10,
            image: 'http://dummyimage.com/1214x1024.jpg/cc0000/ffffff',
            floatingText: 'lacinia',
            createdAt: '2020-03-26 15:17:26',
            updatedAt: '2020-08-26 22:13:14',
            userId: 'c6506639-7ab5-4a8a-8d04-1f694fe6dc5f',
            userName: 'Angelico Ingleby',
            adId: 'fcdae492-4b5a-4451-bdfc-cabb6ab044bb',
        },
    ];

    const responsive = {
        0: { items: 1 },
        250: { items: 3 },
        500: { items: 4 },
    };

    const stories = data.map((story) => {
        const backgroundImage = {
            backgroundImage: `url(${story.image})`,
        };

        return (
            <StoryCard>
                <StoryImage style={backgroundImage}>{story.floatingText ?? ''}</StoryImage>
                <div>{story.userName}</div>
            </StoryCard>
        );
    });

    return (
        <StyledCard elevation={0}>
            <CardHeader title={t('news:recentStories')}></CardHeader>
            <AliceCarousel
                items={stories}
                responsive={responsive}
                disableDotsControls={true}
                activeIndex={activeIndex}
                animationType={'slide'}
            />
            <div>{activeIndex}</div>
            <div>
                <button
                    onClick={() =>
                        activeIndex === 0 ? setActiveIndex(0) : setActiveIndex(activeIndex - 1)
                    }
                >
                    Prev
                </button>
                <button
                    onClick={() =>
                        activeIndex === stories.length - 1
                            ? setActiveIndex(stories.length - 1)
                            : setActiveIndex(activeIndex + 1)
                    }
                >
                    Next
                </button>
            </div>
        </StyledCard>
    );
};

export default StoriesCard;
tiagomota79 commented 3 years ago

Another related issue:

Carousel stop rolling after a few stops on custom button using activeIndex - video below (the number above Previous/Next buttons are the active index. Arrows are default. https://user-images.githubusercontent.com/45611789/104028259-81d38780-5196-11eb-9805-6070fd9cbae0.mp4

maxmarinich commented 3 years ago

Hi, @tiagomota79! So, it's how React works. You create new props (stories && responsive) every time in the render. As a result, the gallery getting new props every time reset or recaclulate inner state . As a solution, save props in the local state or use a code from examples(all of them use TypeScript under hood): activeIndex, refs.