Bind Picker в список Picker.Item in React Native

Я уверен, что есть способ сделать это, но пока еще не вижу.

Что бы я хотел сделать, это добавить компонент Picker, но вместо того, чтобы жестко закодировать список элементов, получить это из службы и связать Picker с тем, что я могу заполнить позже.

Вот что у меня есть, но мое приложение даже не запустится. Любые идеи, пожалуйста?

'use strict';
var React = require('react-native');
var {
    Picker,
    Text,
    View
} = React;

var AvailableServices = React.createClass({
    getInitialState() {
        var fetchServicesUri = 'http://some.url/available_services';
        fetch(fetchServicesUri)
            .then((response) => response.json())
            .then((responseJson) => {
                console.log(responseJson);
                var services = [];
                for(var service in responseJson.services) {
                    services.push(<Picker.Item label={service.Label} value={service.Value}/>);
                }
                this.setState({
                    services: services
                });
            })
            .catch((error) => {
                console.warn(error);
            })
            .done();
        return {
            services: [],
            selectedService: null
        }
    },

    render() {
        return (
            <View>
                <Text>Pick a service</Text>
                <Picker
                    selectedValue={this.state.selectedService}
                    onValueChange={(service) => this.setState({selectedService:service})}
                >
                    {this.state.services}
                </Picker>
            </View>
        );
    }
});

module.exports = AvailableServices;

Ответ 1

Вероятно, вы должны настроить свое начальное состояние как пустой массив, а затем вызвать свою службу на componentWillMount или componentDidMount. Я создал что-то, что работает с некоторыми фиктивными данными здесь, и вставлял код ниже.

'use strict';
var React = require('react-native');
var {
    Picker,
    Text,
    View,
      AppRegistry
} = React;

var PickerItem = Picker.Item;

var SampleApp = React.createClass({
    getInitialState() {
        return {
            services: ['a', 'b', 'c', 'd', 'e'],
            selectedService: 'a'
        }
    },

    componentDidMount() {
        setTimeout(() =>  { 
         this.setState({
          services: [ 'one', 'two', 'three', 'four', 'five' ]
         }) 
        }, 3000)
    },

    render() {
        let serviceItems = this.state.services.map( (s, i) => {
            return <Picker.Item key={i} value={s} label={s} />
        });

        return (
            <View>
                <Text>Pick a service</Text>
                <Picker
                    selectedValue={this.state.selectedService}
                    onValueChange={ (service) => ( this.setState({selectedService:service}) ) } >

                    {serviceItems}

                </Picker>
            </View>
        );
    }
});


AppRegistry.registerComponent('SampleApp', () => SampleApp);

Ответ 2

Никаких циклов не требуется, вот как я это сделал в своем проекте с исходной базой данных, аналогичном приведенному выше ответу для динамического связывания или добавления данных в Picker

import React, {Component} from 'react';
import {Picker,View} from 'react-native';
export default class SampleApp extends Component  {

    constructor(props){
        super(props);
        // HARD CODED DATA , YOU CAN REPLACE THIS DATA  WITH API CALL DATA IN ComponentDidMount() 
       //or in Constructor because countryData is not state.
        this.countryData = ["India","Pakistan","USA"];
        // STATE    
        this.state({
            selectedCountry : null
        });
    }
    // Our country list generator for picker
    countryList = () =>{
        return( this.countryData.map( (x,i) => { 
              return( <Picker.Item label={x} key={i} value={x}  />)} ));
    }
    // RENDER
    render() {
        return (
            <View>
                <Picker
                    selectedValue={this.state.selectedCountry}
                    onValueChange={ (value) => ( this.setState({selectedCountry : value}) )}>
                    { this.countryList() }
                </Picker>
            </View>
        );
    }
}

Надеюсь, вы найдете мой пример простым для понимания;)

Ответ 3

Вы можете попробовать это.

<Picker
      selectedValue={this.state.facilityId}
      style={{ width: '100%' }}
      onValueChange={(itemValue) => this.setState({ facilityId: itemValue, facilityPicked: true })}>
      {facilities.map((facility, i) => {
        return <Picker.Item key={i} value={facility.id} label={facility.facility_name} />
      })}
</Picker>

Здесь средства - это список объектов, имеющих в качестве ключа идентификатор и имя объекта.

Ответ 4

Я получил ту же ошибку. Проблема не в сборщике, а в коде.

let items = props.category.map((item,index) => {
     return ( <Picker.Item key={index} label={item.category} value={item.category} /> )
   })
  return(
         <Picker style={styles.pickerStyle}>{items}</Picker>
        );

Вместо использования item.category я использовал item.name что привело к остановке моего приложения. Поэтому проверьте ценность ваших данных.

Ответ 5

ВАЖНО: если вы попытаетесь перебрать массив чисел с map, не забудьте, что свойство label для Picker.Item должно быть преобразовано в строку:

const pickerItems = [1,2,3].map(i => (
      <Picker.Item label={i.toString()} value={i} />
));