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

React Native中如何通过首个Picker值调用API填充第二个Picker

问题分析与解决方案

核心问题总结

你的第二个Picker无数据返回,主要是以下几个代码错误导致的:

  • 箭头函数语法错误:getBanksByCountry中解析响应的代码写错,导致无法正确获取银行数据
  • 未触发银行API调用:选中国家时没有调用getBanksByCountry函数
  • useEffect无限循环:缺少依赖数组,导致重复调用获取国家的API
  • 状态赋值错误:在获取国家列表时错误地给单个状态赋值数组属性
  • 函数组件误用类组件语法:TextInput中使用this.setState,不符合函数组件规范

修正后的完整代码

import {
  ImageBackground,
  Modal,
  ScrollView,
  StyleSheet,
  Text,
  TextInput,
  TouchableOpacity,
  View,
  Platform
} from 'react-native';
import {Picker} from '@react-native-picker/picker';
import React, {useEffect, useState} from 'react';
import {useNavigation} from '@react-navigation/native';
import BackgroundOpacity from './BackgroundOpacity';

const InternationalPayments = () => {
  const navigation = useNavigation();
  const [banks, setBanks] = useState([]);
  const [countries, setCountries] = useState([]);
  const [selectedCountry, setSelectedCountry] = useState();
  const [selectedBank, setSelectedBank] = useState();
  const [modalVisible, setModalVisible] = useState(false);
  // 为TextInput定义对应的状态
  const [creditAccount, setCreditAccount] = useState('');
  const [amount, setAmount] = useState('');
  const [narration, setNarration] = useState('');
  const [branchCode, setBranchCode] = useState('');
  const [beneficiaryName, setBeneficiaryName] = useState('');

  const getBanksByCountry = (symbol) =>{
    // 修复箭头函数语法错误
    fetch(`https://api.flutterwave.com/v3/banks/${symbol}`,{
      method:'GET',
      headers:{
        'Content-type': 'application/json',
        'Authorization': 'Bearer FLWSECK_TEST-72fe360edef17334f4817a17407011bb-X',
      },
    }).then(response => response.json())
      .then(responseJson =>{
        setBanks(responseJson.data);
        // 去掉多余的单个银行状态赋值,因为banks是数组,单个状态无意义
      })
      .catch(error => {
        // 添加错误捕获,方便调试
        console.error('获取银行数据失败:', error);
      })
  }

  const getAllCountries = async () =>{
    fetch('https://webserver-migospay.onrender.com/api/location/get-country',{
      method:'GET',
      headers:{
        'Content-type': 'application/json'
      },
    }).then(response => response.json())
      .then(responseJson=>{
        setCountries(responseJson.data);
        // 去掉错误的单个国家状态赋值,因为返回的是数组
      })
      .catch(error => {
        console.error('获取国家数据失败:', error);
      })
  }

  // 添加依赖数组,只在组件挂载时调用一次
  useEffect(()=>{
    getAllCountries();
  }, [])

  // 监听selectedCountry变化,调用银行API
  useEffect(()=>{
    if(selectedCountry){
      getBanksByCountry(selectedCountry);
    }
  }, [selectedCountry])

  return (
    <View style={styles.container}>
      <BackgroundOpacity
        display={Platform.OS === 'ios' ? false : modalVisible}
      />
      <View style={styles.space} />
      <ScrollView
        contentContainerStyle={{
          justifyContent: 'space-between',
          alignItems: 'center',
        }}>
        <ImageBackground
          source={{
            uri: "asset:/logo/bg.JPG",
          }}
          imageStyle={{borderRadius: 6}}
          style={{
            top: -30,
            paddingTop: 95,
            alignSelf: "center",
            width: 328,
            height: 115,
            borderRadius: 9,
            justifyContent: "center",
            alignItems: "center",
          }}>
          <View>
            <Text style={styles.accText}>Wallet Balance</Text>
            <Text style={styles.text}> 250,000 </Text>
          </View>
        </ImageBackground>

        <View
          style={{
            borderRadius: 5,
            borderWidth: 1,
            overflow: 'hidden',
            height: 53,
            padding: 0,
            borderColor: '#00BB23',
          }}>
          <Picker
            style={{
              width: 300,
              height: 55,
              borderBottomWidth: 1,
            }}
            itemStyle={{
              fontSize: 25,
              fontFamily: 'Poppins-Medium',
            }}
            selectedValue={selectedCountry}
            onValueChange={(value) => setSelectedCountry(value)}
          >
            <Picker.Item label="Select Country" value="" />
            {countries.map((country, index) => (
              <Picker.Item label={country.country_name} value={country.symbol} key={index} />
            ))}
          </Picker>
        </View>
        
        <View style={styles.space}/>
        <View
          style={{
            borderRadius: 5,
            borderWidth: 1,
            overflow: 'hidden',
            height: 53,
            padding: 0,
            borderColor: '#00BB23',
          }}>
          <Picker
            style={{
              width: 300,
              height: 55,
              borderBottomWidth: 1,
            }}
            itemStyle={{
              fontSize: 25,
              fontFamily: 'Poppins-Medium',
            }}
            selectedValue={selectedBank}
            onValueChange={(value) => setSelectedBank(value)}
            disabled={!selectedCountry} // 未选国家时禁用银行Picker
          >
            <Picker.Item label="Select Bank" value="" />
            {banks.map((bank, index) => (
              <Picker.Item label={bank.name} value={bank.code} key={index} />
            ))}
          </Picker>
        </View>
        
        <View style={styles.space2}/>
        <TextInput
          placeholder="Destination Account"
          onChangeText={setCreditAccount}
          value={creditAccount}
          style={styles.input}
        />

        <TextInput
          placeholder=" Amount"
          onChangeText={setAmount}
          value={amount}
          style={styles.input}
        />

        <TextInput
          placeholder=" Narration"
          onChangeText={setNarration}
          value={narration}
          style={styles.input}
        />

        <TextInput
          placeholder=" Destination Branch Code"
          onChangeText={setBranchCode}
          value={branchCode}
          style={styles.input}
        />

        <TextInput
          placeholder=" Beneficiary Name"
          onChangeText={setBeneficiaryName}
          value={beneficiaryName}
          style={styles.input}
        />

        <View
          style={{
            borderRadius: 5,
            borderWidth: 1,
            overflow: 'hidden',
            height: 35,
            padding: 0,
            top: 10,
            borderColor: '#00BB23',
          }}>
          <Picker
            style={{
              width: 300,
              height: 53,
              borderBottomWidth: 1,
            }}
            itemStyle={{
              fontSize: 25,
              fontFamily: 'Poppins-Medium',
            }}>
            <Picker.Item label="Currency" value="accNum" />
            <Picker.Item label="NGN" value="NGN" />
          </Picker>
        </View>

        <TouchableOpacity
          onPress={() => {
            setModalVisible(true);
          }}
          style={styles.button}>
          <Text style={styles.loginbtn}> Transfer </Text>
        </TouchableOpacity>
        <Modal
          hasBackdrop={true}
          backdropOpacity={0.2}
          backdropColor="black"
          transparent
          visible={modalVisible}
          onRequestClose={() => setModalVisible(false)}>
          <View style={styles.modal}>
            <Text>Hello From Modal</Text>
            <TouchableOpacity onPress={() => setModalVisible(false)}>
              <Text>Close Modal</Text>
            </TouchableOpacity>
          </View>
        </Modal>
      </ScrollView>
    </View>
  );
};

export default InternationalPayments;

const styles = StyleSheet.create({
  container: {
    paddingTop: 40,
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'space-between',
  },

  modal: {
    top: '50%',
    height: '50%',
    backgroundColor: '#fff',
  },
  accText: {
    top: -50,
    paddingTop: 10,
    justifyContent: 'center',
    alignItems: 'center',
    fontFamily: 'Poppins-Medium',
    fontSize: 12,
    color: 'white',
    textAlign: 'center',
  },
  text: {
    top: -50,
    fontSize: 20,
    color: 'white',
    textAlign: 'center',
    fontFamily: 'Poppins-Bold',
  },
  input: {
    top: 10,
    width: 300,
    height: 53,
    margin: 10,
    fontSize: 12,
    borderColor: '#00BB23',
    fontFamily: 'Poppins-Bold',
    borderRadius: 5,
    borderWidth: 1,
    marginBottom: 30,
  },

  button: {
    marginTop: 40,
    width: 150,
    height: 50,
    padding: 10,
    borderRadius: 10,
    backgroundColor: '#00BB23',
    alignItems: 'center',
  },

  Regbutton: {
    width: 150,
    height: 52,
    padding: 10,
    borderRadius: 10,
    backgroundColor: '#ffffff',
    alignItems: 'center',
    borderWidth: 2,
    borderColor: '#030303',
  },

  loginbtn: {
    color: '#ffff',
    fontSize: 15,
    fontFamily: 'Poppins-Medium',
  },

  AccountBalance: {
    fontSize: 13,
    fontWeight: 'bold',
    textAlign: 'left',
  },

  loginbtn2: {
    color: '#030303',
    fontSize: 20,
    fontWeight: 'bold',
  },

  logo: {
    width: 150,
    height: 150,
  },

  space: {
    top: 10,
    width: 10,
    height: 20,
  },

  space2: {
    width: 10,
    height: 10,
  },

  imageStyle: {
    flexDirection: 'row',
    justifyContent: 'center',
    padding: 5,
    margin: 2,
    height: 15,
    width: 15,
    resizeMode: 'stretch',
    marginBottom: 8,
    marginTop: 8,
    alignItems: 'center',
  },
});

关键修正点说明

  1. 修复箭头函数语法:将response = response.json()改为response => response.json(),确保正确解析API响应
  2. 添加国家选中监听:新增useEffect监听selectedCountry变化,一旦选中国家就调用getBanksByCountry获取对应银行数据
  3. 修正useEffect依赖:给获取国家的useEffect添加空依赖数组[],避免无限循环调用API
  4. 移除错误状态赋值:删除getAllCountries中对country_name和country_symbol的错误赋值,因为返回的是国家数组,无法直接取单个属性
  5. 替换TextInput的setState:为每个TextInput定义对应的useState状态,使用函数组件的方式处理输入值
  6. 优化用户体验:未选中国家时禁用银行Picker,避免无效操作
  7. 添加错误捕获:在fetch请求中添加catch块,方便调试API调用失败的情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 08:45:17