首页 > 解决方案 > react-native-deck-swiper 如何在 react-native-deck-swiper 中传递动态引用?

问题描述

我不习惯使用 ref,所以我有一个问题。我正在使用 react-native-deck-swiper 来显示一些卡片。人们可以通过刷卡投票。尽可能清楚:

这是显示我的 swipers 的 json:

{
            "id": 577,
            "type": "copernic",
            "entity": {
                "id": 715,
                "str_id": "rCckubRTIDz2D3N5wcKW",
                "display_name": "Force Républicaine",
                "name": "Force Républicaine",
                "title": "Dépense publique",
                "description": null,
                "type": 2,
                "str_type": "Pour / Contre / Neutre",
                "is_opened": 1,
                "str_is_opened": "Les utilisteurs peuvent soumettre des propositions",
                "order_propositions_by": 3,
                "display_votes": 1,
                "login_to_vote": 0,
                "str_login_to_vote": "Les utilisateurs ne doivent pas se connecter pour voter",
                "login_to_send_proposition": 1,
                "str_login_to_send_proposition": "Les utilisateurs doivent se connecter pour envoyer une proposition",
                "begins_at": "2021-03-02T17:45:55.000000Z",
                "ends_at": null,
                "propositions": [
                    {
                        "id": 6572,
                        "title": "Pensez-vous qu'il faille annuler la dette COVID ?",
                        "description": "",
                        "auteur": "Force Républicaine",
                        "type": 1,
                        "media_link": null,
                        "video_frame": null
                    },
                    {
                        "id": 6571,
                        "title": "Trouvez-vous la qualité des services publics en France à la hauteur du niveau de la dépense publique du pays ?",
                        "description": "",
                        "auteur": "Force Républicaine",
                        "type": 1,
                        "media_link": null,
                        "video_frame": null
                    }
                ]
            },
            "is_pinned": 0,
            "created_at": "2021-03-18T13:27:03.000000Z"
        },

因此,每个 swipers 都可以作为 ref、theitem.entity.iditem.entity.id.

我的刷卡器显示item.entity.propositions为卡片。每张卡片都有拇指可以向右,向上或向左投票。我需要一个 ref 来做一些事情,比如swiperRef.current.swipeRight()当我们点击拇指或告诉用户这个刷卡器的每张卡片都已通过显示消息刷卡时。现在消息显示在所有刷卡器上,这不是我想要的:)

这是我的 swiper 的代码:

if (
      item.type === "copernic" &&
      item.entity.str_type === "Pour / Contre / Neutre"
    ) {
       return (
         <View style={styles.swipperWrapper} key={item.id}>
          {isSwipedAll ? (
            <View style={styles.emptyCopernic}>
              <View style={styles.emptyCopernicColor} />
              <View style={styles.copContainer}>
                <Text style={styles.copTitle}>
                  You have swiped all the cards! Thanx for your participation !
                </Text>
              </View>
            </View>
          ) : (
            <Swiper
              ref={useSwiper}
              //animateCardOpacity
              containerStyle={styles.swiperContainer}
              cards={item.entity.propositions}
              renderCard={(card, index) => (
                <CardCopernic
                  {...index}
                  copKey={card.id}
                  copTitle={card.title}
                  copDesc={card.description}
                  strid={strid}
                  onPressNo={() => swipeLeft(card.id, index)}
                  onPressMaybe={() => swipeTop(card.id, index)}
                  onPressYes={() => swipeRight(card.id, index)}
                />
              )}
              onSwipedLeft={(card) => handleNo(card)}
              onSwipedTop={(card) => handleMaybe(card)}
              onSwipedRight={(card) => handleYes(card)}
              onSwipedAll={onSwipedAllCards}
              cardIndex={cardIndex}
              stackSize={3}
              stackScale={5}
              showSecondCard
              backgroundColor="white"
              cardVerticalMargin={2}
              disableBottomSwipe
              overlayLabels={{
                left: {
                  title: "Contre",
                  style: {
                    label: {
                      borderColor: "#FF8585",
                      color: "#FF8585",
                      borderWidth: 2,
                    },
                    wrapper: {
                      flexDirection: "column",
                      alignItems: "flex-end",
                      justifyContent: "flex-start",
                      marginTop: 30,
                      marginLeft: -30,
                    },
                  },
                },
                right: {
                  title: "Pour",
                  style: {
                    label: {
                      borderColor: "#FF8585",
                      color: "#FF8585",
                      borderWidth: 2,
                    },
                    wrapper: {
                      flexDirection: "column",
                      alignItems: "flex-start",
                      justifyContent: "flex-start",
                      marginTop: 30,
                      marginLeft: 30,
                    },
                  },
                },
                top: {
                  title: "Neutre",
                  style: {
                    label: {
                      borderColor: "#FF8585",
                      color: "#FF8585",
                      borderWidth: 2,
                    },
                    wrapper: {
                      flexDirection: "column",
                      alignItems: "center",
                      justifyContent: "center",
                    },
                  },
                },
              }}
            />
          )}
        </View>
      );

这是向左、向右或向上刷卡的功能之一:

swipeLeft = async (cardId, index) => {
        console.log("CARDINDEX : ", index);

        const cardKey = cardId;
        const strid = item.entity.str_id;
        const token = await AsyncStorage.getItem("token");
        useSwiper.current[strid].swipeLeft(cardId);

        const requestOptions = {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "X-Requested-With": "XMLHttpRequest",
            Authorization: `Bearer ${token}`,
          },
          body: JSON.stringify({
            vote: "contre",
            proposition_id: `${cardKey}`,
            consultation_str_id: `${strid}`,
          }),
        };

        try {
          let response = await fetch(
            `${c.API_URL_DEV}/copernic/vote/add`,
            requestOptions
          );
          let json = await response.json();
          if (index === item.entity.propositions.length - 1) {
            setSwipedAll(true);
            await AsyncStorage.setItem("hasAllSwiped", JSON.stringify(true));
          }
          return json;
        } catch (error) {
          console.error(error);
        }
      };

任何帮助表示赞赏!我有点卡在这里,对裁判不太熟悉哈哈 x 我的项目是功能组件:)

如果您需要更多信息来帮助,请告诉我!:)

标签: react-nativereact-hooksuse-refreact-native-swiper

解决方案


尝试将相关的 swiper 代码封装到一个组件中。这将消除对动态引用的需要并正确封装状态。

就像是:

function MySwiper({item}) {
  const swiperRef = useRef(null);
  const [isSwipedAll, setSwipedAll] = useState(false);
  const swipeLeft = useCallback(async (cardId, index) => {
    console.log("CARDINDEX : ", index);

    const cardKey = cardId;
    const strid = item.entity.str_id;
    const token = await AsyncStorage.getItem("token");
    swiperRef.current.swipeLeft(cardId);

    const requestOptions = {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-Requested-With": "XMLHttpRequest",
        Authorization: `Bearer ${token}`,
      },
      body: JSON.stringify({
        vote: "contre",
        proposition_id: `${cardKey}`,
        consultation_str_id: `${strid}`,
      }),
    };

    try {
      let response = await fetch(
        `${c.API_URL_DEV}/copernic/vote/add`,
        requestOptions
      );
      let json = await response.json();
      if (index === item.entity.propositions.length - 1) {
        setSwipedAll(true);
        await AsyncStorage.setItem("hasAllSwiped", JSON.stringify(true)); // TODO: index this somehow by the item
      }
      return json;
    } catch (error) {
      console.error(error);
    }
  }, [item]);

  return (
    <View style={styles.swipperWrapper} key={item.id}>
      {isSwipedAll ? (
        <View style={styles.emptyCopernic}>
          <View style={styles.emptyCopernicColor} />
          <View style={styles.copContainer}>
            <Text style={styles.copTitle}>
              You have swiped all the cards! Thanx for your participation !
            </Text>
          </View>
        </View>
      ) : (
        <Swiper
          ref={useSwiper}
          //animateCardOpacity
          containerStyle={styles.swiperContainer}
          cards={item.entity.propositions}
          renderCard={(card, index) => (
            <CardCopernic
              {...index}
              copKey={card.id}
              copTitle={card.title}
              copDesc={card.description}
              strid={strid}
              onPressNo={swipeLeft}
              onPressMaybe={() => swipeTop(card.id, index)} // UPDATE
              onPressYes={() => swipeRight(card.id, index)} // UPDATE
            />
          )}
          onSwipedLeft={(card) => handleNo(card)} // UPDATE
          onSwipedTop={(card) => handleMaybe(card)} // UPDATE
          onSwipedRight={(card) => handleYes(card)} // UPDATE
          onSwipedAll={onSwipedAllCards}
          cardIndex={cardIndex}
          stackSize={3}
          stackScale={5}
          showSecondCard
          backgroundColor="white"
          cardVerticalMargin={2}
          disableBottomSwipe
          overlayLabels={...}
        />
      )}
    </View>
  );
}

您需要创建其他回调并修复它们在 AsyncStorage 中存储的状态,以便根据每个项目进行键控。


推荐阅读