Mike
Mike

Reputation: 6239

Bind Picker to list of Picker.Item in React Native

I'm sure there is a way to do this, but I just can't see how yet.

What I'd like to do, is add a Picker component, but rather than hard-code the list of items, fetch this from a service and have the Picker bound to something I can populate later.

Here's what I have, but my app won't even run now. Any ideas please?

'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;

Upvotes: 26

Views: 53466

Answers (6)

Ritveak
Ritveak

Reputation: 3788

Question:

I am using map which is a data structure introduced in JS in ES6.

I am using Picker for the dropdown. here's my code :

<Picker
            selectedValue={this.state.branch}
            style={styles.fieldPicker}
            mode="dropdown"

            onValueChange={(itemValue, itemIndex) =>
              this.setState({branch: itemValue})
            }>

            {/* Data Binding */}

                {this.state.branchData.forEach((name, id) => 
                      {
                      return <Picker.Item key={id} value={id} label={name} />;
                      })
                }



          </Picker>

I checked if name and id are being correctly accessed by logging it. The issue is that I am not able to see the dropdown getting populated.

Upvotes: 0

Ilarion Halushka
Ilarion Halushka

Reputation: 2343

IMPORTANT: if you try to iterate an array of numbers with map then don't forget that label property of Picker.Item should be converted to string:

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

Upvotes: 9

Rahul Kumar
Rahul Kumar

Reputation: 1

I got the same error. The problem is not with picker but instead, with your code.

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>
        );

Instead of using item.category, i was using item.name which caused my app to stop. So check the value of your data.

Upvotes: 0

Abhishek Garg
Abhishek Garg

Reputation: 3242

No Loops required, here how i did in my react native based project, similar to above answer to bind or add data dynamically in 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>
        );
    }
}

Hope you find my example simple to understand ;)

Upvotes: 7

Yash Mochi
Yash Mochi

Reputation: 967

You can try this one.

<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>

Here, facilities is a list of object having id and facility_name as key.

Upvotes: 2

Nader Dabit
Nader Dabit

Reputation: 53711

You should probably set up your initial state as the empty array, then call your service on componentWillMount or componentDidMount. I've set up something that works with some dummy data here, and pasted the code below.

'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);

Upvotes: 55

Related Questions