Javascript 在React Native中调用两次静态函数
为了改进我的应用程序的结构,我将大多数应用程序内购买功能移动到一个带有静态方法和变量的特殊类中 当我尝试使用这个类时,函数似乎每次调用两次,即使在我的代码中,我只调用它们一次。当我使用Chrome中的远程调试和(1)处的断点对其进行调试时,它确实达到了该断点两次,当我查看stacktrace时,这两次都是从Javascript 在React Native中调用两次静态函数,javascript,reactjs,function,class,react-native,Javascript,Reactjs,Function,Class,React Native,为了改进我的应用程序的结构,我将大多数应用程序内购买功能移动到一个带有静态方法和变量的特殊类中 当我尝试使用这个类时,函数似乎每次调用两次,即使在我的代码中,我只调用它们一次。当我使用Chrome中的远程调试和(1)处的断点对其进行调试时,它确实达到了该断点两次,当我查看stacktrace时,这两次都是从App.js中的componentDidMount()调用的 在App.js的 import IAPManager from "./helpers/IAPManager"; ... async
App.js中的componentDidMount()
调用的
在App.js的
import IAPManager from "./helpers/IAPManager";
...
async componentDidMount() {
await IAPManager.prepare(); // (1) debug breakpoint
}
async componentWillUnmount() {
await IAPManager.endConnection();
}
我还在另一个组件中调用IAPManager
的方法:
import IAPManager from "../../helpers/IAPManager";
...
async componentDidMount() {
const isConnected = await NetInfo.isConnected.fetch();
if (!isConnected) {
console.log("Not connected to the internet");
Alert.alert(
"No connection",
"Uh oh, looks like you aren't connected to the internet, which you need to be to take advantage of Premium",
[{text: "OK"}]
);
} else {
let hasPurchasedPremium;
try {
hasPurchasedPremium = await IAPManager.isPremiumUnlocked();
} catch (e) {
console.log("Failed to check if premium is unlocked", e);
hasPurchasedPremium = false;
}
this.setState({ hasPurchasedPremium: hasPurchasedPremium });
if (hasPurchasedPremium) {
console.log("Has purchased premium");
} else {
console.log("Hasn't purchased premium");
const premiumProduct = await IAPManager.getPremiumProductInfo();
this.setState({ premiumProduct: premiumProduct });
}
}
}
IAPManager
类如下所示:
import * as InAppPurchase from 'react-native-iap';
import { AsyncStorage, Platform } from "react-native";
const itemSKUs = Platform.select({
android: [
"unlock_premium"
]
});
export default class IAPManager {
static hasUnlockedPremium = undefined;
static productInfo = undefined;
static async prepare() {
await InAppPurchase.prepare();
console.log("done preparing");
}
static async endConnection() {
await InAppPurchase.endConnection();
}
static async getProductInfo() {
console.log("getProductInfo");
try {
const products = await InAppPurchase.getProducts(itemSKUs);
IAPManager.productInfo = products;
console.log("finished call to get products", IAPManager.productInfo);
} catch (e) {
console.log(e);
}
}
static async getPremiumProductInfo() {
console.log("getPremiumProductInfo");
if (IAPManager.productInfo === undefined) {
await this.getProductInfo();
}
const premiumProduct = IAPManager.productInfo.filter(product => product.productId === "unlock_premium");
return premiumProduct[0];
}
static async isPremiumUnlocked() {
console.log("isPremiumUnlocked");
if (IAPManager.hasUnlockedPremium !== undefined) {
return IAPManager.hasUnlockedPremium;
}
IAPManager.hasUnlockedPremium = true; // TODO: remove this when done testing
return IAPManager.hasUnlockedPremium;
}
}
05-04 23:58:34.354 15867 20588 I ReactNativeJS: isPremiumUnlocked
05-04 23:58:34.370 15867 20588 I ReactNativeJS: Hasn't purchased premium
05-04 23:58:34.370 15867 20588 I ReactNativeJS: getPremiumProductInfo
05-04 23:58:34.384 15867 20588 I ReactNativeJS: isPremiumUnlocked
05-04 23:58:34.385 15867 20588 I ReactNativeJS: getProductInfo
05-04 23:58:34.388 15867 20588 I ReactNativeJS: isPremiumUnlocked
05-04 23:58:34.403 15867 20588 I ReactNativeJS: Hasn't purchased premium
05-04 23:58:34.403 15867 20588 I ReactNativeJS: getPremiumProductInfo
05-04 23:58:34.419 15867 20588 I ReactNativeJS: isPremiumUnlocked
05-04 23:58:34.422 15867 20588 I ReactNativeJS: getProductInfo
05-04 23:58:34.424 15867 20588 I ReactNativeJS: 'finished call to get products', [ { description: 'With premium you can set more than two timers at the same time.',
05-04 23:58:34.424 15867 20588 I ReactNativeJS: title: 'Unlock Premium',
05-04 23:58:34.424 15867 20588 I ReactNativeJS: localizedPrice: '19,00 kr',
05-04 23:58:34.424 15867 20588 I ReactNativeJS: type: 'inapp',
05-04 23:58:34.424 15867 20588 I ReactNativeJS: currency: 'SEK',
05-04 23:58:34.424 15867 20588 I ReactNativeJS: price: '19.00',
05-04 23:58:34.424 15867 20588 I ReactNativeJS: productId: 'unlock_premium' } ]
05-04 23:58:34.426 15867 20588 I ReactNativeJS: done preparing
05-04 23:58:34.666 15867 20588 I ReactNativeJS: 'finished call to get products', [ { description: 'With premium you can set more than two timers at the same time.',
05-04 23:58:34.666 15867 20588 I ReactNativeJS: title: 'Unlock Premium',
05-04 23:58:34.666 15867 20588 I ReactNativeJS: localizedPrice: '19,00 kr',
05-04 23:58:34.666 15867 20588 I ReactNativeJS: type: 'inapp',
05-04 23:58:34.666 15867 20588 I ReactNativeJS: currency: 'SEK',
05-04 23:58:34.666 15867 20588 I ReactNativeJS: price: '19.00',
05-04 23:58:34.666 15867 20588 I ReactNativeJS: productId: 'unlock_premium' } ]
05-04 23:58:34.668 15867 20588 I ReactNativeJS: done preparing
最后,我得到的日志如下所示:
import * as InAppPurchase from 'react-native-iap';
import { AsyncStorage, Platform } from "react-native";
const itemSKUs = Platform.select({
android: [
"unlock_premium"
]
});
export default class IAPManager {
static hasUnlockedPremium = undefined;
static productInfo = undefined;
static async prepare() {
await InAppPurchase.prepare();
console.log("done preparing");
}
static async endConnection() {
await InAppPurchase.endConnection();
}
static async getProductInfo() {
console.log("getProductInfo");
try {
const products = await InAppPurchase.getProducts(itemSKUs);
IAPManager.productInfo = products;
console.log("finished call to get products", IAPManager.productInfo);
} catch (e) {
console.log(e);
}
}
static async getPremiumProductInfo() {
console.log("getPremiumProductInfo");
if (IAPManager.productInfo === undefined) {
await this.getProductInfo();
}
const premiumProduct = IAPManager.productInfo.filter(product => product.productId === "unlock_premium");
return premiumProduct[0];
}
static async isPremiumUnlocked() {
console.log("isPremiumUnlocked");
if (IAPManager.hasUnlockedPremium !== undefined) {
return IAPManager.hasUnlockedPremium;
}
IAPManager.hasUnlockedPremium = true; // TODO: remove this when done testing
return IAPManager.hasUnlockedPremium;
}
}
05-04 23:58:34.354 15867 20588 I ReactNativeJS: isPremiumUnlocked
05-04 23:58:34.370 15867 20588 I ReactNativeJS: Hasn't purchased premium
05-04 23:58:34.370 15867 20588 I ReactNativeJS: getPremiumProductInfo
05-04 23:58:34.384 15867 20588 I ReactNativeJS: isPremiumUnlocked
05-04 23:58:34.385 15867 20588 I ReactNativeJS: getProductInfo
05-04 23:58:34.388 15867 20588 I ReactNativeJS: isPremiumUnlocked
05-04 23:58:34.403 15867 20588 I ReactNativeJS: Hasn't purchased premium
05-04 23:58:34.403 15867 20588 I ReactNativeJS: getPremiumProductInfo
05-04 23:58:34.419 15867 20588 I ReactNativeJS: isPremiumUnlocked
05-04 23:58:34.422 15867 20588 I ReactNativeJS: getProductInfo
05-04 23:58:34.424 15867 20588 I ReactNativeJS: 'finished call to get products', [ { description: 'With premium you can set more than two timers at the same time.',
05-04 23:58:34.424 15867 20588 I ReactNativeJS: title: 'Unlock Premium',
05-04 23:58:34.424 15867 20588 I ReactNativeJS: localizedPrice: '19,00 kr',
05-04 23:58:34.424 15867 20588 I ReactNativeJS: type: 'inapp',
05-04 23:58:34.424 15867 20588 I ReactNativeJS: currency: 'SEK',
05-04 23:58:34.424 15867 20588 I ReactNativeJS: price: '19.00',
05-04 23:58:34.424 15867 20588 I ReactNativeJS: productId: 'unlock_premium' } ]
05-04 23:58:34.426 15867 20588 I ReactNativeJS: done preparing
05-04 23:58:34.666 15867 20588 I ReactNativeJS: 'finished call to get products', [ { description: 'With premium you can set more than two timers at the same time.',
05-04 23:58:34.666 15867 20588 I ReactNativeJS: title: 'Unlock Premium',
05-04 23:58:34.666 15867 20588 I ReactNativeJS: localizedPrice: '19,00 kr',
05-04 23:58:34.666 15867 20588 I ReactNativeJS: type: 'inapp',
05-04 23:58:34.666 15867 20588 I ReactNativeJS: currency: 'SEK',
05-04 23:58:34.666 15867 20588 I ReactNativeJS: price: '19.00',
05-04 23:58:34.666 15867 20588 I ReactNativeJS: productId: 'unlock_premium' } ]
05-04 23:58:34.668 15867 20588 I ReactNativeJS: done preparing
感谢您阅读本文,我感谢您的帮助:) 在调用componentDidMount
内部的setState
时要小心,这可能是导致重新呈现并再次调用的问题。此外,仅在视图中使用的变量上设置状态。如果您没有在视图中使用它们,请不要使它们处于状态。让它们成为正则变量。看起来你可能正在使用。我想你可能是对的,Tomasz,我试着运行我的应用程序的生产版本,但它没有显示方法的双重调用。谢谢相关问题;这是为React本机应用程序运行“安装”和“拆卸”代码的推荐方法吗?在iOS开发中,我记得我将这种代码放在AppDelegate
文件中,该文件具有applicationdifinishLaunching
和applicationWillTerminate