React-native-iap: PurchaseUpdatedListenerが繰り返し呼び出されます

作成日 2020年02月03日  ·  6コメント  ·  ソース: dooboolab/react-native-iap

react-native-iapのバージョン

4.3.0

react-nativeのバージョン

0.60.5

エラーに直面したプラットフォーム(IOSまたはAndroid、あるいはその両方?)

どちらも

予想される行動

例に従って、サブスクリプションを購入した後にカスタムメソッドを呼び出します。 購入を確認した後、リスナーを削除する必要があることは私の理解です。 remove明示的に呼び出しようとしましたが、成功しませんでした。

 const purchaseListener = purchaseUpdatedListener(purchase => {
      const receipt = purchase.transactionReceipt;
      if (receipt) {
        callCustomEndpoint().then(result => {
          if(result){
            // Subscription is valid
            finishTransaction(purchase);
          }
        }) 
      };
      finishTransaction(purchase);
    });

実際の動作

callCustomEndpoint()メソッドが複数回呼び出されています。 どうすればこれを防ぐことができますか? このエンドポイントに到達する必要があるのは1回だけです。

重要な場合は、クラスコンポーネントの代わりに機能コンポーネントを使用しています。

テストされた環境(エミュレーター?実デバイス?)

実デバイス

動作を再現する手順

🙏 help wanted

最も参考になるコメント

後でそれを必要とする人のために、フックの解決策を書き留めます。

状態コンポーネントの外部(おそらく内部でも機能します):

var purchaseUpdateSubscription;
var purchaseErrorSubscription;
const loadIAPListeners = () => {
  initConnection(); // important, or else it won't trigger before a random state change
  purchaseUpdateSubscription = purchaseUpdatedListener(
    async (
      purchase: InAppPurchase | SubscriptionPurchase | ProductPurchase,
    ) => {
      console.log('purchaseUpdatedListener', purchase);
      let receipt = purchase.transactionReceipt;
      if (receipt) {
        apis.checkreceipt({data: purchase, platform: Platform.OS}); // I personally don't care about callback
        if (Platform.OS === 'ios') {
          await RNIap.finishTransactionIOS(purchase.transactionId);
        } else if (Platform.OS === 'android') {
          await RNIap.acknowledgePurchaseAndroid(purchase.purchaseToken);
        }
        await RNIap.finishTransaction(purchase, true);
        await RNIap.finishTransaction(purchase, false);
      } else {
        // Retry / conclude the purchase is fraudulent, etc...
      }
    },
  );
  purchaseErrorSubscription = purchaseErrorListener((error: PurchaseError) => {
    console.log('purchaseErrorListener', error);
  });
};

状態コンポーネント内:

useEffect(() => {
    loadIAPListeners();
    return () => {
      purchaseUpdateSubscription.remove();
      purchaseErrorSubscription.remove();
    };
  }, []);

全てのコメント6件

コンポーネントが再レンダリングされるときに、purchaseListenerを複数回登録したと思われます。

おかげで、各レンダリングで呼び出されないように、フックを使用してこれを書き直しました。 私の間違いは、クラスコンポーネントのドキュメントで提供されている例を取り上げて、それを機能コンポーネントに移植しようとしたことでした。 図書館で素晴らしい仕事をしました!

@cgathergood私もこの問題を抱えています。 反応フックを使用してイベントハンドラーコードを投稿してもよろしいですか?

@cgathergoodコードサンプルも見たいです。 私はフックに少し苦労しています。

@ wootwoot1234 @osmantunaなんとか修正できたら、イベントハンドラーコードを

後でそれを必要とする人のために、フックの解決策を書き留めます。

状態コンポーネントの外部(おそらく内部でも機能します):

var purchaseUpdateSubscription;
var purchaseErrorSubscription;
const loadIAPListeners = () => {
  initConnection(); // important, or else it won't trigger before a random state change
  purchaseUpdateSubscription = purchaseUpdatedListener(
    async (
      purchase: InAppPurchase | SubscriptionPurchase | ProductPurchase,
    ) => {
      console.log('purchaseUpdatedListener', purchase);
      let receipt = purchase.transactionReceipt;
      if (receipt) {
        apis.checkreceipt({data: purchase, platform: Platform.OS}); // I personally don't care about callback
        if (Platform.OS === 'ios') {
          await RNIap.finishTransactionIOS(purchase.transactionId);
        } else if (Platform.OS === 'android') {
          await RNIap.acknowledgePurchaseAndroid(purchase.purchaseToken);
        }
        await RNIap.finishTransaction(purchase, true);
        await RNIap.finishTransaction(purchase, false);
      } else {
        // Retry / conclude the purchase is fraudulent, etc...
      }
    },
  );
  purchaseErrorSubscription = purchaseErrorListener((error: PurchaseError) => {
    console.log('purchaseErrorListener', error);
  });
};

状態コンポーネント内:

useEffect(() => {
    loadIAPListeners();
    return () => {
      purchaseUpdateSubscription.remove();
      purchaseErrorSubscription.remove();
    };
  }, []);
このページは役に立ちましたか?
0 / 5 - 0 評価