如何用不变的数据大小限制我的 data.length ,这样我就不会超过最后一个索引?反应本机

问题描述 投票:0回答:1

我有两个列表组件或卡片堆栈。 5 副牌,每副牌中有几张牌。我列出了 5 个牌组,并在我单击具有 (selectedItem) 状态的子组件时将其内容传递给子组件。然后我在它的子组件中选取它,并用里面的卡片映射另一个平面列表。

我的问题是,当我单击超出较小甲板限制的索引时。例如,

牌组 1 = 23 张牌 Deck2 = 15 张卡

当我在 Deck1 上索引+1 到超过 15 的任意位置,并尝试单击 Deck2 时,它说它超出范围(显然哈哈),我希望在更换牌组时将其重置为索引(0)。我不能只是添加更多卡片并使它们的数量相同,因为我稍后将设置一个新功能,用户可以构建自己的牌组,并且可以是任意数量的卡片

这是我的套牌组件

const Decks = () => {
  const {theme} = useContext(ThemeContext)
  let activeColors = colors[theme.mode]

  const allbelts = [yellowbelt, orangebelt, greenbelt, brownbeltthree, brownbelttwo, brownbeltone]

  const ref = useRef(null);
  const [selectedItem, setSelectedItem] = useState(null);
  const [deckIndex, setDeckIndex] = useState(0);

  const handleItemPress = (item) => {
    setSelectedItem(item);
    console.log("deckIndex:", deckIndex);
  };

  return (
    <View style={{flex:1}}>
      <View style={{flex:1, marginTop: 40}}>
        <Text style={[{color:activeColors.primary}, styles.sectionheading]}>
          Testing Card Decks
        </Text>
          <Animated.FlatList
            ref={ref}
            data={allbelts}
            horizontal
            keyExtractor={(item, index) => index.toString()}
            showsHorizontalScrollIndicator={false}
            snapToInterval={ITEM_SIZE}
            decelerationRate={0}
            bounces={false}
            scrollEventThrottle={16}
            renderItem={({item, deckIndex}) => (
              <View 
                style={{}}>
                <TouchableOpacity 
                  key={deckIndex}
                  onPress={() => {
                    handleItemPress(item)
                  }}>    
                  <Animated.View 
                    style={[{
                      backgroundColor: item.color,
                      shadowColor: item.color,
                      borderColor: activeColors.bgalt}, 
                      styles.card]}>
                      <Text 
                        numberOfLines={2} 
                        style={[{color: item.color === "#F5D143" ? activeColors.black : activeColors.white}, styles.cardtitle]}>
                        {item.rank_japanese}
                      </Text>
                      <Text 
                        numberOfLines={2} 
                        style={[{color: item.color === "#F5D143" ? activeColors.black : activeColors.white}, styles.cardtitle]}>
                        {item.rank_english}
                      </Text>
                  </Animated.View>
                </TouchableOpacity>
              </View>
            )}
          />   
        <TestingCards selectedItem={selectedItem} deckIndex={deckIndex}  />
      </View>
    </View>
  )
}

export default Decks

这是卡片组件

const Card = ({info}) => {
  const {theme} = useContext(ThemeContext)
  let activeColors = colors[theme.mode]

  const rotate = useSharedValue(0);
  
  const frontAnimatedStyle = useAnimatedStyle(() => {
    const rotateValue = interpolate(
      rotate.value, 
      [0, 1], 
      [0, 180]
    );
    return {
      transform: [
        {rotateY: withTiming(`${rotateValue}deg`, {duration: 500})}
      ]
    }
  })

  const backAnimatedStyle = useAnimatedStyle(() => {
    const rotateValue = interpolate(
      rotate.value, 
      [0, 1], 
      [180, 360]
    );
    return {
      transform: [
        {rotateY: withTiming(`${rotateValue}deg`, {duration: 500})}
      ]
    }
  })
  return (
    <View style={[styles.cardcontainer]}>
      <View style={styles.iconcnt}>
        <Pressable 
          onPress={() => {
            rotate.value = rotate.value ? 0 : 1;  
          }} 
          style={styles.icon}>
          <Icon name="swap-horizontal" size={24} color={activeColors.textcolor} />
        </Pressable>
      </View>
      <View style={styles.cardContent}>
        <Animated.View style={[ {backgroundColor: activeColors.bgalt, position:"absolute"}, styles.card, frontAnimatedStyle]}>
          <View>
            <Text 
              style={[{color: activeColors.textcolor}, styles.cardtext]}>
              {info.q}
            </Text>
          </View>
        </Animated.View>

        <Animated.View style={[ {backgroundColor: activeColors.primary}, styles.card, backAnimatedStyle]}>
          <View>
            <Text 
              style={[{color: activeColors.textcolor}, styles.cardtext]}>
              {info.a}
            </Text>
          </View>          
        </Animated.View>
      </View>
    </View>
    
  )
}

const FlashCards = ({selectedItem, deckIndex}) => {
  const {theme} = useContext(ThemeContext)
  let activeColors = colors[theme.mode]

  const [index, setIndex] = useState(0);
  const [lastIndex, setLastIndex] = useState(null);
  const [viewPosition, setViewPosition] = useState(0.5);

  const flatlistRef = useRef(null)

  useEffect(() => {
    setLastIndex(selectedItem?.questions?.length - 1);

    // console.log("selectedItem:", selectedItem);
    console.log("lastIndex at TestingCards:", lastIndex);

    flatlistRef.current?.scrollToIndex({
      index: index, 
      animated: true,
      viewPosition,
    })
  } , [index, viewPosition, lastIndex, selectedItem])

  if (!selectedItem) {
    return null;
  }
  return (
    <View style={[styles.container]}>
      <Animated.FlatList
        data={selectedItem.questions}   
        ref={flatlistRef}
        index={deckIndex}           
        keyExtractor={(item, index) => index.toString()}
        initialScrollIndex={0}
        horizontal
        showsHorizontalScrollIndicator={false}
        snapToInterval="ITEM_SIZE"
        decelerationRate={0}
        bounces={false}
        scrollEventThrottle={16}
        initialNumToRender={10} 
        onScrollToIndexFailed={index => {
            setIndex(0) 
          const wait = new Promise(resolve => setTimeout(resolve, 0));
          wait.then(() => {
            flatlistRef.current?.scrollToIndex({ index: index, animated: true });
          });
        }}
        renderItem={({item, index}) => <Card info={item} index={index} totalLength={lastIndex} seefront={true} />}
      />
      <View style={styles.btnGroup}>
        <TouchableOpacity 
          onPress={()=>{
            setIndex(0);
            setViewPosition(0.5);
          }}>
          <LinearGradient
            colors={['rgba(1,102,175,1)', 'rgba(155,24,213,1)']}
            start={{ x: 0, y: 1 }}
            end={{ x: 1, y: 1 }}
            style={styles.btnPrimary}>
            <Icon name="chevron-double-left" size={24} color={activeColors.white} />
          </LinearGradient>
        </TouchableOpacity>      
        <TouchableOpacity 
          onPress={()=>{
            if (index === 0) {
              return;
            }
            setIndex(index - 1);
            setViewPosition(0.5);
          }}>
          <LinearGradient
            colors={['rgba(1,102,175,1)', 'rgba(155,24,213,1)']}
            start={{ x: 0, y: 1 }}
            end={{ x: 1, y: 1 }}
            style={styles.btnPrimary}>
            <Icon name="chevron-left" size={24} color={activeColors.white} />
          </LinearGradient>
        </TouchableOpacity>               
        <TouchableOpacity 
          onPress={()=>{
            if (index === lastIndex) {
              return;
            }
            setIndex(index + 1);
            setViewPosition(0.5);
          }}>
          <LinearGradient
            colors={['rgba(1,102,175,1)', 'rgba(155,24,213,1)']}
            start={{ x: 0, y: 1 }}
            end={{ x: 1, y: 1 }}
            style={styles.btnPrimary}>
            <Icon name="chevron-right" size={24} color={activeColors.white} />
          </LinearGradient>
        </TouchableOpacity>   
        <TouchableOpacity 
          onPress={()=>{

            if (index === lastIndex) {
              return;
            }
            setIndex(lastIndex - 1);
            setViewPosition(0.5); 
          }}>
          <LinearGradient
            colors={['rgba(1,102,175,1)', 'rgba(155,24,213,1)']}
            start={{ x: 0, y: 1 }}
            end={{ x: 1, y: 1 }}
            style={styles.btnPrimary}>
            <Icon name="chevron-double-right" size={24} color={activeColors.white} />
          </LinearGradient>
        </TouchableOpacity>            
      </View>
    </View>
  )
}

export default FlashCards
javascript reactjs react-native
1个回答
0
投票
useEffect(()=>{
 setIndex(0)
}, [deckIndex])

每当牌组索引更改时,它会将索引重置为 0,另一方面,每当您选择不同的牌组时。 这是你想做的吗?

© www.soinside.com 2019 - 2024. All rights reserved.