首页 > 解决方案 > 城市数据未显示在选择器中

问题描述

我想在选择器 kota/kabupaten 中显示城市数据,但是从选择器 propinsi 中选择省份后,数据没有出现。请帮忙解决这个问题

这是选择省份后总是返回null的代码:

getCitiesData = (currentProvince) => {
const cities = {}
if (currentProvince) {
  this.props.cities.forEach(city => {
    cities[city.id] = city.id ? city.city.toString() : city.city.toString()
  })
}
return t.enums(cities)

}

这里是检查所选选择器省值的代码:

formChange(newValue) {
console.log('===form change===');
console.log(newValue)
console.log(this.state.formValue.province);

const { formValue } = this.state
const { province } = newValue


if (formValue.province !== province) {
  console.log(`province choosed = ${province}`);
  this.setState({ currentProvince: parseInt(province)});
  this.fetchCitiesByProvince(parseInt(province));
}

this.setState({
  formValue: newValue
})
console.log('=================');

}

这是完整的代码:

  constructor(props) {
    super(props)
    this.state = {
      currentProvince: null,
      formModel: t.struct({
        id: t.Number,
        bookingOrderId: t.String,
        title: Title,
        senderName: t.String,
        senderMobile: t.String,
        senderEmail: t.String,
        senderAddress: t.String,
        recipientName: t.String,
        recipientMobile: t.String,
        goodTypeOrder: GoodTypeOrder,
        goodWeight: t.Number,
        length: t.Number,
        wide: t.Number,
        high: t.Number,
        address1: t.String,
        address2: t.String,
        address3: t.String,
        postalCode: t.String,
        province: this.getProvincesData(),
        city: this.getCitiesData(),
        subDistrict: t.String,
        urbanVillage: t.String,
        additionalFacility: t.list(Fasilitas),
        bookingNotes: t.String,
        schedule: t.Number,
        whoOrdered: t.Number
      }),

      formValue: { id: null, schedule: this.props.data.scheduleId, whoOrdered: this.props.account.id, province: null },
      formOptions: {
        fields: {
          id: {
            hidden: true
          },
          schedule: {
            testID: 'routeScheduleIdInput',
            hidden: true
          },
          whoOrdered: {
            testID: 'userIdInput',
            hidden: true
          },
          bookingOrderId: {
            testID: 'bookingOrderIdInput',
            hidden: true
          },
          title: {
            label: 'titel',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('title').refs.input.focus(),
            testID: 'titleInput',
            stylesheet: stylesheet
          },
          senderName: {
            label: 'nama lengkap pengirim',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('senderName').refs.input.focus(),
            testID: 'senderNameInput',
            stylesheet: stylesheet
          },
          senderMobile: {
            label: 'nomor telepon selular pengirim',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('senderMobile').refs.input.focus(),
            testID: 'senderMobileInput',
            template: notel,
            stylesheet: stylesheet
          },
          senderEmail: {
            label: 'email pengirim',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('senderEmail').refs.input.focus(),
            testID: 'senderEmailInput',
            stylesheet: stylesheet,
            autoCapitalize: 'none'
          },
          senderAddress: {
            label: 'alamat pengirim',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('senderAddress').refs.input.focus(),
            testID: 'senderAddressInput',
            stylesheet: stylesheet
          },
          recipientName: {
            label: 'nama lengkap penerima',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('recipientName').refs.input.focus(),
            testID: 'recipientNameInput',
            stylesheet: stylesheet
          },
          recipientMobile: {
            label: 'nomor telepon selular penerima',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('recipientMobile').refs.input.focus(),
            testID: 'recipientMobileInput',
            template: notel,
            stylesheet: stylesheet
          },
          goodTypeOrder: {
            label: 'jenis barang',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('goodTypeOrder').refs.input.focus(),
            testID: 'goodTypeOrderInput',
            stylesheet: stylesheet
          },
          goodWeight: {
            label: 'berat barang',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('goodWeight').refs.input.focus(),
            testID: 'goodWeightInput',
            keyboardType: 'numeric',
            stylesheet: stylesheet,
            template: berat
          },
          length: {
            label: 'panjang',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('length').refs.input.focus(),
            testID: 'lengthInput',
            keyboardType: 'numeric',
            stylesheet: stylesheet,
            template: panjang
          },
          wide: {
            label: 'lebar',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('wide').refs.input.focus(),
            testID: 'wideInput',
            keyboardType: 'numeric',
            stylesheet: stylesheet,
            template: lebar
          },
          high: {
            label: 'tinggi',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('tinggiBarangPemesan').refs.input.focus(),
            testID: 'highInput',
            keyboardType: 'numeric',
            stylesheet: stylesheet,
            template: tinggi
          },
          address1: {
            label: 'alamat penerima baris 1',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('address1').refs.input.focus(),
            testID: 'address1Input',
            stylesheet: stylesheet
          },
          address2: {
            label: 'alamat penerima baris 2',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('address2').refs.input.focus(),
            testID: 'address2Input',
            stylesheet: stylesheet
          },
          address3: {
            label: 'alamat penerima baris 3',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('address3').refs.input.focus(),
            testID: 'address3Input',
            stylesheet: stylesheet
          },
          postalCode: {
            label: 'kode pos',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('postalCode').refs.input.focus(),
            testID: 'postalCodeInput',
            keyboardType: 'numeric',
            stylesheet: stylesheet
          },
          province: {
            label: 'propinsi',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('province').refs.input.focus(),
            testID: 'provinceInput',
            stylesheet: stylesheet
          },
          city: {
            label: 'kota / kabupaten',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('city').refs.input.focus(),
            testID: 'cityInput',
            stylesheet: stylesheet
          },
          subDistrict: {
            label: 'kecamatan',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('subDistrict').refs.input.focus(),
            testID: 'subDistrictInput',
            stylesheet: stylesheet
          },
          urbanVillage: {
            label: 'kelurahan',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('urbanVillage').refs.input.focus(),
            testID: 'urbanVillageInput',
            stylesheet: stylesheet
          },
          additionalFacility: {
            label: 'fasilitas tambahan',
            returnKeyType: 'next',
            onSubmitEditing: () => this.refs.form.getComponent('additionalFacility').refs.input.focus(),
            testID: 'additionalFacilityInput',
            factory: t.form.formModel,
            stylesheet: stylesheet
          },
          bookingNotes: {
            label: 'catatan pengiriman',
            multiline: true,
            onSubmitEditing: () => this.refs.form.getComponent('bookingNotes').refs.input.focus(),
            testID: 'bookingNotesInput',
            stylesheet: stylesheet
          },

        }
      },
      bookingOrder: {},
      success: false
    }

    this.submitForm = this.submitForm.bind(this)
    this.formChange = this.formChange.bind(this)
  }

  // convenience methods for customizing the mapping of the entity to/from the form value
  entityToFormValue = (value) => {
    if (!value) {
      return {}
    }
    return {
      id: value.id || null,
      bookingOrderId: value.bookingOrderId || null,
      title: value.title || null,
      senderName: value.senderName || null,
      senderMobile: value.senderMobile || null,
      senderEmail: value.senderEmail || null,
      senderAddress: value.senderAddress || null,
      recipientName: value.recipientName || null,
      recipientMobile: value.recipientMobile || null,
      goodTypeOrder: value.goodTypeOrder || null,
      goodWeight: value.goodWeight || null,
      length: value.length || null,
      wide: value.wide || null,
      high: value.high || null,
      address1: value.address1 || null,
      address2: value.address2 || null,
      address3: value.address3 || null,
      postalCode: value.postalCode || null,
      province: value.province && value.province.id ? value.province.id : null,
      city: value.city && value.city.id ? value.city.id : null,
      subDistrict: value.subDistrict || null,
      urbanVillage: value.urbanVillage || null,
      additionalFacility: value.additionalFacility || null,
      bookingNotes: value.bookingNotes || null,
      schedule: value.routeSchedule && value.routeSchedule.id ? value.routeSchedule.id : null,
      whoOrdered: value.account && value.account.id ? value.account.id : null
      //vehicleDriversId: value.vehicleDrivers && value.vehicleDrivers.id ? value.vehicleDrivers.id : null,
      //vehicleId: value.vehicle && value.vehicle.id ? value.vehicle.id : null,
      //customerTruckId: value.customerTruck && value.customerTruck.id ? value.customerTruck.id : null
    }
  }
  formValueToEntity = (value) => {
    const entity = {
      id: value.id || null,
      bookingOrderId: value.bookingOrderId || null,
      title: value.title || null,
      senderName: value.senderName || null,
      senderMobile: value.senderMobile || null,
      senderEmail: value.senderEmail || null,
      senderAddress: value.senderAddress || null,
      recipientName: value.recipientName || null,
      recipientMobile: value.recipientMobile || null,
      goodTypeOrder: value.goodTypeOrder || null,
      goodWeight: value.goodWeight || null,
      length: value.length || null,
      wide: value.wide || null,
      high: value.high || null,
      address1: value.address1 || null,
      address2: value.address2 || null,
      address3: value.address3 || null,
      postalCode: value.postalCode || null,
      //city: value.city || null,
      subDistrict: value.subDistrict || null,
      urbanVillage: value.urbanVillage || null,
      additionalFacility: value.additionalFacility.toString() || null,
      bookingNotes: value.bookingNotes || null
    }
    if (value.province) {
      entity.province = value.province.toString()
    }
    if (value.city) {
      entity.city = value.city.toString()
    }
    if (value.schedule) {
      entity.schedule = { id: value.schedule, price: this.props.routeSchedule.price };
    }
    if (value.whoOrdered) {
      entity.whoOrdered = { id: value.whoOrdered };
    }

    /**
    if (value.routeScheduleId) {
      entity.routeSchedule = { id: value.routeScheduleId };
    }
    if (value.userId) {
      entity.user = { id: value.userId };
    }
    if (value.vehicleDriversId) {
      entity.vehicleDrivers = { id: value.vehicleDriversId };
    }
    if (value.vehicleId) {
      entity.vehicle = { id: value.vehicleId };
    }
    if (value.customerTruckId) {
      entity.customerTruck = { id: value.customerTruckId };
    }**/
    console.log('===entity order truck===');
    console.log(entity);
    return entity
  }

  getProvincesData = (newPropsProvinces) => {
    const provinces = {}
    this.props.provinces.forEach(province => {
      provinces[province.id] = province.id ? province.name.toString() : province.name.toString()
    })
    return t.enums(provinces)
  }

  componentWillMount() {
    this.props.getRouteSchedule(this.props.data.scheduleId);
    this.props.getAllProvinces({ page: 0, sort: 'id,asc', size: 20 });
    this.fetchCitiesByProvince()
    //this.props.getAllCities({ page: 0, sort: 'id,asc', size: 20 });
  }

  submitForm() {
    // call getValue() to get the values of the form
    const bookingOrder = this.refs.form.props.value;
    //console.log(bookingOrder);
    if (bookingOrder) {
      // if validation fails, value will be null
      this.props.updateBookingOrder(this.formValueToEntity(bookingOrder));
      //const { booking } = this.state;
      //truckPaymentScreen({booking: bookingOrder.id});
    }

  }

  formChange(newValue) {
    console.log('===form change===');
    console.log(newValue)
    console.log(this.state.formValue.province);

    const { formValue } = this.state
    const { province } = newValue


    if (formValue.province !== province) {
      console.log(`province choosed = ${province}`);
      this.setState({ currentProvince: parseInt(province)});
      this.fetchCitiesByProvince(parseInt(province));
    }

    this.setState({
      formValue: newValue
    })
    console.log('=================');
  }

  fetchCitiesByProvince = (currentProvince) => {
    console.log('fetch api get city by province')
    console.log(this.props)
    this.props.getAllCitiesByProvince({ province: currentProvince })
  }

  getCitiesData = (currentProvince) => {
    const cities = {}
    if (currentProvince) {
      this.props.cities.forEach(city => {
        cities[city.id] = city.id ? city.city.toString() : city.city.toString()
      })
    }
    return t.enums(cities)
  }


  render() {
    console.log('===render screen===');
    console.log(this.state);
    console.log(this.props);
    console.log('===================');

    if (!this.props.routeSchedule){
      return (
        <View>
          <Text>Loading...</Text>
        </View>
      );
    }
    const formatted_price = numeral(this.props.routeSchedule.price).format('0,0[.]00');
    const departure_date = moment(this.props.routeSchedule.departureTime);
    const arrival_date = moment(this.props.routeSchedule.arrivalTime);
    const duration = calculateDuration(departure_date, arrival_date);
    //const rowTestID = `schedule_${item.id}`;
    return (
      <View style={styles.container}>
        <ScrollView style={styles.barTop}>
          <View style={styles.topRow}>
            <View style={styles.textTopRow}>
              <Text style={styles.textTime}></Text>
              <Text style={styles.textTime}>{this.props.routeSchedule.departureCity}</Text>
            </View>
            <View>
              <Image source={Images.arrow} style={styles.icon} />
            </View>
            <View style={styles.textTopRow}>
              <Text style={styles.textTime}></Text>
              <Text style={styles.textTime}>{this.props.routeSchedule.arrivalCity}</Text>
            </View>
          </View>
          <View style={styles.boxList}>
              <View style={styles.contain}>
                <Image style={styles.smallLogo} source={this.props.routeSchedule.companyPicture} />
                <Text style={styles.textCompany}>{this.props.routeSchedule.brand}</Text>
                <Text style={styles.textCompanyFull}> | {this.props.routeSchedule.company}</Text>
              </View>
                <View style={{flexDirection:'row'}}>
                  <View style={{ flex: 2, marginLeft: 20, marginTop: 5}}>
                    <Text style={{ fontSize: 10 }}>o</Text>
                    <Text style={{ fontSize: 10 }}>|</Text>
                    <Text style={{ fontSize: 10 }}>o</Text>
                    <Text style={{ fontSize: 10 }}>|</Text>
                    <Text style={{ fontSize: 10 }}>o</Text>
                  </View>
                  <View style={{ flex: 62, justifyContent:'space-between',marginBottom: 15}}>
                      <View style={styles.departureDate}>
                          <Text style={styles.textDepartureTime}>{departure_date.format('HH:mm')}</Text>
                          <Text style={styles.textDepartureCity}>Kota {this.props.routeSchedule.departureCity}</Text>
                          <View style={{flex: 0.1}}></View>
                          <Text style={styles.textCooler}>{this.props.routeSchedule.coolerType}</Text>
                      </View>
                      <View style={{ flexDirection: 'row' }}>
                          <View style={styles.textRow}>{renderDuration(duration)}</View>
                      </View>
                      <View style={styles.arrival_date}>
                          <Text style={styles.textArrivalTime}>{arrival_date.format('HH:mm')}</Text>
                          <Text style={styles.textArrivalCity}>Kota {this.props.routeSchedule.arrivalCity}</Text>
                          <Text style={styles.textPrice}>Rp. {formatted_price}</Text>
                      </View>
                  </View>
                </View>
            </View>
          <Text style={styles.textPemesan}>Detail Pemesan</Text>
          <Form
            ref='form'
            type={this.state.formModel}
            options={this.state.formOptions}
            value={this.state.formValue}
            onChange={this.formChange}
          />
          <TouchableHighlight style={styles.button}
            onPress={this.submitForm}
            underlayColor='#99d9f4' testID='submitButton'>
            <Text style={styles.buttonText}>pembayaran</Text>
          </TouchableHighlight>
        </ScrollView>
      </View>
    )
  }
}

const mapStateToProps = (state) => {
  console.log('||=== state2props form-order ===||');
  console.log(state);
  console.log('||=== ======================= ===||');
  return {
    //routeSchedules: state.routeSchedules.routeSchedules || [],
    routeSchedule: state.routeSchedules.routeSchedule,
    provinces: state.provinces.provinces,
    cities: state.cities.cities,
    citiesByProvince: state.cities.citiesByProvince,
    subDistricts: state.subDistricts.subDistricts,
    subDistrictsByCity: state.subDistricts.subDistrictsByCity,
    urbanVillages: state.urbanVillages.urbanVillages,
    urbanVillagesBySubDistrict: state.urbanVillages.urbanVillagesBySubDistrict,
    account: state.account.account,
    fetching: state.bookingOrders.fetchingOne,
    error: state.bookingOrders.errorUpdating,
    bookingOrder: state.bookingOrders.bookingOrder,
    booking: state.bookingOrderBills.booking
  }
}

const mapDispatchToProps = (dispatch) => {
  console.log('||==Dispatch to Props==||');
  console.log(BookingOrderActions);
  return {
    getAllProvinces: (options) => dispatch(ProvinceActions.provinceAllRequest(options)),
    getAllCitiesByProvince: (province) => dispatch(CityActions.cityAllByProvinceRequest(province)),
    getAllSubDistrictsByCity: (city) => dispatch(SubDistrictActions.subDistrictAllByCityRequest(city)),
    getAllUrbanVillagesBySubDistrict: (subDistrict) => dispatch(UrbanVillageActions.urbanVillageAllByKecamatanRequest(subDistrict)),
    getRouteSchedule: id => dispatch(RouteScheduleActions.routeScheduleRequest(id)),
    getAccount: () => dispatch(AccountActions.accountRequest()),
    updateBookingOrder: bookingOrder => dispatch(BookingOrderActions.bookingOrderUpdateRequest(bookingOrder)),
    findBillbyBookingOrder: (booking) => dispatch(BookingOrderBillActions.bookingOrderBillByBookingOrderRequest(booking))
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(TruckOrderScreen)```


标签: react-nativeforeachtcomb-form-native

解决方案


以这种方式使用您的代码:

const citiesJson = this.getCitiesData();
const cities = Tcomb.enums(citiesJson);

formModel: t.struct({
...
  name: t.String,
  city: cities,
  address: t.String,
...
});

如果它不起作用,请确保您的函数 getCitiesData() 以 JSON 类型返回正确的数据,或者以这种方式使用准备好的 JSON 文件来检查代码是否有效:

cities = require('./cities.json');

city.json 应该是这样的:

{
    "1": "Aleppo",
    "2": "Jeddah",
    "3": "Istanbul",
}

推荐阅读