leecade / react-native-swiper

The best Swiper component for React Native.
MIT License
10.4k stars 2.34k forks source link

active dot does not update on swipe when children have changed #971

Open macrozone opened 5 years ago

macrozone commented 5 years ago

Which OS ?

IOS and android

Version

Which versions are you using:

Expected behaviour

the active dot changes when i swipe

Actual behaviour

the first dot is always highlighted

How to reproduce it>

 <Swiper>
          {items.map(item => (
            <View key={item._id}><Text>{item.label}</Text></View>
          ))}
</Swiper>

Steps to reproduce

  1. make sure that items is empty first []
  2. on a later render. fill items with some objects
  3. active dot is now broken

Workaround:

 <Swiper key={items.length}>
          {items.map(item => (
            <View key={item._id}><Text>{item.label}</Text></View>
          ))}
</Swiper>
retyui commented 5 years ago

This repo dead: https://github.com/leecade/react-native-swiper/issues/713 Your issue is like other 480+ issues, will not be resolved in the short term.

macrozone commented 5 years ago

@retyui not very constructive to add this link to every issue. If you want to help, do a fork or write the maintainer a personal email and ask to put you as maintainer here.

retyui commented 5 years ago

I wrote authors in the mail, two months ago and a week ago, I did not receive an answer, an absolute ignore

legion-zver commented 5 years ago

@macrozone use patch-package and my patch file:

diff --git a/node_modules/react-native-swiper/src/index.js b/node_modules/react-native-swiper/src/index.js
index d9deeb4..d22bcf8 100644
--- a/node_modules/react-native-swiper/src/index.js
+++ b/node_modules/react-native-swiper/src/index.js
@@ -396,8 +396,9 @@ export default class extends Component {
     let index = state.index
     if (!this.internals.offset)   // Android not setting this onLayout first? https://github.com/leecade/react-native-swiper/issues/582
       this.internals.offset = {}
-    const diff = offset[dir] - this.internals.offset[dir]
-    const step = dir === 'x' ? state.width : state.height
+
+    const diff = (offset[dir] || 0) - (this.internals.offset[dir] || 0)
+    const step = (dir === 'x' ? state.width : state.height) || 0
     let loopJump = false

     // Do nothing if offset no change.
fabOnReact commented 5 years ago

@macrozone

@retyui is right.. why use this repo when you can just build the functionality with Scroll View and a couple of lines of code

What is the point of using a library with 500 open issues

dannam83 commented 4 years ago

a year later it's still not resolved. but this will make it work: set the key to the length of your items.

<Swiper key={items.length} style={styles.swiper}> {items} </Swiper>

rt012 commented 4 years ago

Alternative horizontal Swiper Component:

import React, {useRef, useState} from 'react'; import { Image, View, Dimensions, StyleSheet, TouchableOpacity, useWindowDimensions, ScrollView, Text, } from 'react-native'; import Ionicons from 'react-native-vector-icons/SimpleLineIcons';

const Swiper = ({items,showDots= true,labelProperty = "name", showArrows = true, children, marginVertical = 0, labelColor ="white"}) => { const scrollViewRef = useRef(); const [currentIndex, setCurrentIndex] = useState(0); const [elementWidth, setElementWidth] = useState(0); const [windowWidth, setWindowWidth] = useState( Dimensions.get('window').width)

const updateElementWidth = value => { if (value != elementWidth) { setElementWidth(value); } };

const updateCurrentIndex = index => { setCurrentIndex(index); scrollViewRef.current.scrollTo({x: index * elementWidth}); };

return (

{ if ( event.nativeEvent.contentOffset.x && event.nativeEvent.contentOffset.x / elementWidth != currentIndex ) { setCurrentIndex(event.nativeEvent.contentOffset.x / elementWidth); } else if (event.nativeEvent.contentOffset.x / elementWidth == 0) { setCurrentIndex(0); } }} height={'100%'} showsHorizontalScrollIndicator={false} showsVerticalScrollIndicator={false} removeClippedSubviews={false} width={windowWidth - marginVertical} scrollEnabled={true} loop={false} index={currentIndex} activeDotStyle={{backgroundColor: 'white', height: 10, width: 10}} paginationStyle={{ bottom: -40, }} dotStyle style={styles.wrapper} showsButtons={false}> {children.length > 0 && children.map(child => { return ( { updateElementWidth(e.nativeEvent.layout.width); }} style={{ overflow: 'visible', width: Dimensions.get('screen').width - marginVertical, }}> {child}
          );
        })}
    </ScrollView>
  </View>
  {showArrows && items && items.length > 1 && (
    <View
      style={{marginTop: 10, flexDirection: 'row', alignItems: 'center'}}>
      {currentIndex > 0 ? (
        <TouchableOpacity
          onPress={() => {
            updateCurrentIndex(currentIndex - 1);
          }}
          style={{
            flex: 1,
            padding: 4,
            flexDirection: 'row',
            alignItems: 'center',
          }}>
          <Ionicons size={18} name={'arrow-left'} color={labelColor} />
          <Text style={{marginLeft: 5, color: labelColor}}>
            {items[currentIndex][labelProperty]}
          </Text>
        </TouchableOpacity>
      ) : (
        <View style={{flex: 1}} />
      )}
      {showDots ?
      <View
        style={{
          flexDirection: 'row',
          flex: 1,
          textAlign: 'center',
          justifyContent: 'center',
        }}>
        {items &&
          items.map((location, index) => {
            return (
              <View
                style={{
                  borderRadius: 5,
                  margin: 2,
                  height: 10,
                  width: 10,
                  backgroundColor:
                    index == currentIndex
                      ? labelColor
                      : "#ffffff33"
                }}
              />
            );
          })}
      </View>
        : <View style={{flex: 1}}></View>}
      {showArrows && items  && typeof items[currentIndex + 1] != 'undefined' ? (
        <TouchableOpacity
          onPress={() => {
            updateCurrentIndex(currentIndex + 1);
          }}
          style={{
            flex: 1,
            padding: 4,
            flexDirection: 'row',
            alignItems: 'center',
          }}>
          <Text style={{marginLeft: 5,color: labelColor}}>
            {items[currentIndex + 1][labelProperty]}
          </Text>
          <Ionicons size={18} name={'arrow-right'} color={labelColor} />
        </TouchableOpacity>
      ) : (
        <View style={{flex: 1}} />
      )}
    </View>
  )}
</View>

); };

const styles = StyleSheet.create({ wrapper: { flexDirection: 'row', overflow: 'visible' }, });

export default Swiper;