meliorence / react-native-snap-carousel

Swiper/carousel component for React Native featuring previews, multiple layouts, parallax images, performant handling of huge numbers of items, and more. Compatible with Android & iOS.
BSD 3-Clause "New" or "Revised" License
10.31k stars 2.28k forks source link

onBeforeSnapToItem not working properly #839

Open vkpdeveloper opened 3 years ago

vkpdeveloper commented 3 years ago

Hey, I am using this package in my app, but when I am dragging from one item to another onBeforeSnapToItem called on every scroll, it gives me only one index (1) every time.

Code:

import React, { Component, useState } from 'react';
import {
  View,
  StyleSheet,
  Image,
  Dimensions,
  TouchableOpacity,
  Text,
  Animated,
  FlatList,
  TouchableWithoutFeedback,
  ActivityIndicator
} from 'react-native';
import styled from 'styled-components/native';
import BottomTabBar from '../components/BottomNavigation';
import BuzzFeed from '../components/BuzzFeed';
import CategoryTab from '../components/CategoryTab';
import { useSelector, useDispatch } from 'react-redux';
import R from '../res/R';
import StoryBoard from '../components/Story/StoryBoard';
import ApiHelper from '../controllers/ApiHelper';
import { fillCategories, fillArticles } from '../store/actions';
import Carousel from 'react-native-snap-carousel';

const Dashboard = (props) => {
  let categories = useSelector(state => state.category);
  let [currentPaggingIndex, setCurrentPaggingIndex] = useState(0);
  const dispatcher = useDispatch();
  categories = [{

    "category_id": "mix_bag",
    "category_name": "Mix Bag",
    "category_image": "http://www.gothru.in/uploads/2019061717313125-CATEGORY-8.jpg"

  }, ...categories]

  const allStories = useSelector(state => state.article);
  let [currentArticles, setCurrentArticles] = useState(allStories)
  const [currentCategory, setCurrentCategory] = useState(categories[0].category_id);
  const [screenToShow, setScreenToShow] = useState(2);
  const [isLoading, setIsLoading] = useState(false);

  const handleCategoryChange = async (item) => {
    setCurrentCategory(item.category_id);
    setIsLoading(true);
    let resArticles;
    if (item.category_id === "mix_bag") {
      resArticles = await ApiHelper.getArticle();
    } else {
      resArticles = await ApiHelper.getArticle(item.category_id);
    }
    if (resArticles) {
      const articles = resArticles.data.article_list;
      dispatcher(fillArticles(articles));
      setIsLoading(false);
    }

  }

  const renderItem = ({ item }) => (
    <TouchableWithoutFeedback>
      <StoryBoard type="category" navigate={props.navigate} stories={stories} category={item} />
    </TouchableWithoutFeedback>
  );
  const renderTabItem = ({ item }) => (
    <TouchableOpacity onPress={() => handleCategoryChange(item)}>
      <View style={currentCategory === item.category_id ? styles.tabItemSelected : styles.tabItem}>
        <TabMenuText>{item.category_name}</TabMenuText>
      </View>
    </TouchableOpacity>
  );

  const renderStoryBoard = ({ item, index }) => (
    <View style={{
      flex: 1,
      width: R.dimens.screenWidth,
      alignContent: "center",
      justifyContent: "center",
      alignItems: "center",
      alignSelf: "center"
    }}>
      <StoryBoard type="category" category={currentCategory} navigate={props.navigation} stories={currentArticles} />
    </View>
  );

  // onViewableItemsChanged = async ({ viewableItems, changed }) => {
  //   const { item } = changed[0];
  //   console.log(viewableItems)
  //   console.log('MY ITEM IS : ', item);
  //   if (item.category_id !== "mix_bag") {
  //     setCurrentCategory(changed[0].item.category_id)
  //     setIsLoading(true);
  //     let resArticles;
  //     if (item.category_id === "mix_bag") {
  //       resArticles = await ApiHelper.getArticle();
  //     } else {
  //       resArticles = await ApiHelper.getArticle(item.category_id);
  //     }
  //     if (resArticles) {
  //       const articles = resArticles.data.article_list;
  //       dispatcher(fillArticles(articles));
  //       setIsLoading(false);
  //     }
  //   }
  // }

  const onScrollEnd = async (category) => {
    let resArticles;
    console.log(category);
    if (category === "mix_bag") {
      resArticles = await ApiHelper.getArticle();
    } else {
      resArticles = await ApiHelper.getArticle(category);
    }
    if (resArticles) {
      const articles = resArticles.data.article_list;
      dispatcher(fillArticles(articles));
      setIsLoading(false);
    }
  }

  return (
    <Container style={styles.container}>
      <View>
        {/* Header Logo */}
        <HeaderImage
          style={styles.header_logo}
          source={R.images.header_logo}
        />
        {/* Preference Button */}
        <TouchableOpacity
          style={{ position: 'absolute', alignSelf: 'flex-start' }}
          onPress={() => props.navigation.navigate('Preferences')}>
          <Prefrences
            style={styles.prefrences}
            source={R.images.prefrences}
          />
        </TouchableOpacity>
      </View>

      <View style={{ marginTop: 10 }}></View>
      {/* Category Tab */}
      <View styles={styles.tabBar}>
        <Animated.FlatList
          data={categories}
          keyExtractor={item => item.category_id}
          renderItem={renderTabItem}
          horizontal
          showsHorizontalScrollIndicator={false}
        />
      </View>
      {/*  Category Feed  */}
      {/* <Animated.FlatList
        data={categories}
        keyExtractor={item => item.category_id}
        renderItem={renderItem}
        bounces={false}
        scrollEnabled={false}
        horizontal
        showsHorizontalScrollIndicator={false}
      /> */}
      {
        isLoading ? <View style={{
          flex: 1,
          justifyContent: 'center',
          alignItems: 'center'
        }}>
          <ActivityIndicator size="large" color={R.colors.primary_yellow} />

        </View> : <Carousel
          renderItem={renderStoryBoard}
          data={categories}
          initialNumToRender={categories.length}
          // contentContainerCustomStyle={{
          //   left: 0, // Left spacing for the very first card
          //   paddingRight: 0 //right spacing for very last card 
          // }}
          sliderWidth={R.dimens.screenWidth}
          autoplay={true}
          itemWidth={R.dimens.screenWidth}
          onBeforeSnapToItem={(index) => {
            console.log(index);
            setIsLoading(true);
            console.log(categories[index]);
            setCurrentCategory(categories[index].category_id)
            onScrollEnd(categories[index].category_id);
          }}
          enableMomentum={false}
          // onSnapToItem={index => {
          //   console.log(index);
          //   setIsLoading(true);
          //   console.log(categories[index]);
          //   setCurrentCategory(categories[index].category_id)
          //   onScrollEnd(categories[index].category_id);
          // }}
        >
        </Carousel>

      }
      {/* Floating Bottom Navigation Bar */}
      <BottomTabBar
        onTabChnaged={(index) => {
          setScreenToShow(index)
        }}
      />
    </Container>
  );

}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    // backgroundColor: 'white',
  },
  header_logo: {
    alignSelf: 'center',
    height: R.dimens.screenWidth * 0.125,
    resizeMode: 'contain',
    marginTop: R.dimens.screenWidth * 0.025,
  },
  prefrences: {
    marginTop: R.dimens.screenWidth * 0.05,
    height: R.dimens.screenWidth * 0.08,
    resizeMode: 'contain',
  },
  tabItem: {
    padding: 10,
    marginBottom: 10
  },
  tabItemSelected: {
    backgroundColor: R.colors.primary_yellow,
    padding: 10,
    marginBottom: 10,
    borderRadius: 6
  },
  scene: {
    flex: 1,
  },
  tabBar: {
    marginLeft: 15,
    marginRight: 15
  }
});

const Container = styled.View`
  background: ${(props) => props.theme.background};
`;

const Prefrences = styled.Image`
  tint-color: ${(props) => props.theme.text};
`;

const HeaderImage = styled.Image`
  tint-color: ${(props) => props.theme.text};
`;

const TabMenuText = styled.Text`
  color: ${(props) => props.theme.tab_item_text_color};
`;

export default Dashboard;

Thank you so much.

dohooo commented 2 years ago

@vkpdeveloper Sorry, please allow me to advertise for my open source library! ~ I think this library react-native-reanimated-carousel will solve your problem. It is a high performance and very simple component, complete with React-Native reanimated 2