You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native投币金额累加至2欧元的实现方案咨询

解决React Native投币箱金额累加问题

问题根源

你当前代码里用普通变量coinInserted和totalCoin存储累计金额,这些变量会在组件每次渲染时重置为初始值,导致无法持续累加每次投入的硬币金额。另外条件判断逻辑也存在冗余,需要优化。

解决方案

  1. 用useState管理累计金额:React状态变量会在组件生命周期中保持值,不会随渲染重置。
  2. 优化金额累加逻辑:使用函数式更新状态,确保每次累加都基于最新的累计值。
  3. 处理浮点数精度:由于欧元硬币面值是小数点后两位,累加时可通过乘以100转成整数计算,避免浮点数精度误差。
  4. 重置金额时机:初始化投币箱时重置累计金额,确保每次支付流程从头开始。

修改后的完整代码

import {useNavigation} from '@react-navigation/native';
import React, {useEffect, useState} from 'react';
import {
  Alert,
  NativeEventEmitter,
  NativeModules,
  Pressable,
  StyleSheet,
  Text,
  View,
} from 'react-native';
const {CoinBoxCollector} = NativeModules;

export default function HomeScreen() {
  const navigation = useNavigation();
  // 用state管理累计投币金额,初始为0
  const [totalInserted, setTotalInserted] = useState<number>(0);
  const targetAmount = 2; // 目标支付金额2欧元

  async function onCoinDetected(coin: any) {
    const coinValue = parseFloat(coin);
    // 过滤无效面值(可选,根据硬件返回情况调整)
    if (isNaN(coinValue)) return;

    // 先计算新的累计金额,用整数计算避免精度问题
    const newTotal = Math.round((totalInserted + coinValue) * 100) / 100;

    if (newTotal >= targetAmount) {
      console.log("hai pagato per l' esperienza");
      setTotalInserted(newTotal); // 更新最后一次金额
      await CoinBoxCollector.stop();
      // navigation.navigate('VideoScreen'); // 支付完成后导航到对应页面
      // 支付完成后重置金额,方便下次使用
      setTimeout(() => setTotalInserted(0), 1000);
      return;
    }

    // 未达到目标金额,更新累计值
    setTotalInserted(newTotal);
    console.log(`DEVI INSERIRE ALTRI SOLDI: ${newTotal} / ${targetAmount} €`);
  }

  const pressInit = async () => {
    // 初始化时重置累计金额
    setTotalInserted(0);
    await CoinBoxCollector.initialize();
  };

  const pressStop = async () => {
    console.log('getttoniera stoppata');
    await CoinBoxCollector.stop();
    // 停止时重置金额
    setTotalInserted(0);
  };

  useEffect(() => {
    const eventEmitter = new NativeEventEmitter(NativeModules.CoinBoxCollector);
    const eventListener = eventEmitter.addListener(
      'onReceivedCoin',
      onCoinDetected,
    );
    // 组件卸载时移除监听
    return () => eventListener.remove();
  }, [totalInserted]); // 依赖totalInserted确保监听逻辑正确

  return (
    <View style={styles.container}>
      {/* 显示当前累计金额 */}
      <Text style={styles.amountText}>
        累计投币: {totalInserted.toFixed(2)} € / {targetAmount.toFixed(2)} €
      </Text>
      <Pressable style={styles.btn} onPress={pressInit}>
        <Text style={styles.btnText}>Initialize</Text>
      </Pressable>
      <Pressable style={styles.btn} onPress={pressStop}>
        <Text style={styles.btnText}>Stop it</Text>
      </Pressable>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  btn: {
    marginTop: 30,
    backgroundColor: '#841584',
    width: 120,
    height: 40,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 4,
  },
  btnText: {
    color: 'white',
    fontSize: 16,
  },
  amountText: {
    fontSize: 18,
    marginBottom: 20,
  },
});

关键修改点说明

  • 将coinInserted替换为useState定义的totalInserted,保证金额在组件渲染时不会丢失。
  • 使用Math.round((totalInserted + coinValue) * 100) / 100处理浮点数精度,避免出现0.30000000000000004这类异常值。
  • 在pressInit和pressStop中重置累计金额,确保每次操作都是全新的支付流程。
  • 添加了累计金额的显示,方便用户查看当前投币进度。
  • 修正了原有的条件判断逻辑,简化为判断新的累计金额是否达到目标值。

内容的提问来源于stack exchange,提问作者greta calamari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 17:05:20