Search code examples
firebasereact-nativefirebase-realtime-databasereact-native-picker

Populate Picker items with data from Firebase Realtime Database in React Native


I am trying to use Firebase Realtime Database to populate the items in picker (@react-native-picker/picker) and have failed repeatedly.
I am also attaching a minimal reproducible example below.
Through the onPress event, console.log() is printing the correct array, but I am unable to use it to generate an array for Picker to use.
I would greatly appreciate any help or resources you provide.

import React, { useState } from 'react';
import { StyleSheet, View, Text, Pressable } from 'react-native';
import { Picker } from '@react-native-picker/picker';
import Firebase from './config/firebase';

const Test = () => {
  const [selectedAnimal, setSelectedAnimal] = useState();

  var generateList = (path) => {
    var Listener = Firebase.database().ref(path);
    return Listener.once('value');
  };

  let pickerGenerator = (dblist) => dblist.map(i => {
    return <Picker.Item key={i} label={i.toString()} value={i} />
  });
  
  return (
    <View style={styles.container}>
      <View style={styles.InputContainer}>
      <Picker
        selectedValue={selectedAnimal}
        style={styles.UserInput}
        onValueChange={(itemValue, itemIndex) =>
          setSelectedAnimal(itemValue)
      }>
        {/* {generateList('/Static/Animals').then(data => {
          pickerGenerator(data.val());
        })} */}
      </Picker>
      </View>
      <Pressable
        style={styles.button}
        android_ripple={{ color: 'white' }}
        onPress={() => {
        generateList('/Static/Animals').then(data => {
          console.log(data.val());
        })
      }}>
      <Text style={styles.buttoncontent}>Test</Text>
      </Pressable>
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
    marginHorizontal: 8,
  },
  InputContainer: {
    alignSelf: 'stretch',
    marginBottom: 20,
    borderWidth: 1,
    borderStyle: 'solid',
    borderColor: 'darkviolet',
    borderRadius: 4,
  },
  UserInput: {
    fontSize: 16,
    height: 42,
    paddingHorizontal: 8,
  },
  button: {
    alignItems: 'center',
    justifyContent: 'center',
    paddingVertical: 12,
    paddingHorizontal: 32,
    marginVertical: 5,
    borderRadius: 4,
    elevation: 5,
    backgroundColor: 'cornflowerblue',
  },
  buttoncontent: {
    textAlign: 'center',
    fontSize: 16,
    lineHeight: 24,
    fontWeight: 'bold',
    color: 'white',
  },
});

export default Test;

Solution

  • I got it working through trial and error.

    import React, { useState } from 'react';
    import { StyleSheet, View, Text, Pressable } from 'react-native';
    import { Picker } from '@react-native-picker/picker';
    import Firebase from './config/firebase';
    
    var generated = [];
    
    const Test = () => {
      const [selectedAnimal, setSelectedAnimal] = useState();
    
      var generateList = (path) => {
        var Listener = Firebase.database().ref(path);
        Listener.once('value', (snapshot) => {
          const data = snapshot.val();
          generated = data;
        });
        return generated;
      };
    
      let pickerGenerator = (dblist) => dblist.map(i => {
        return <Picker.Item key={i} label={i.toString()} value={i} />
      });
      
      return (
        <View style={styles.container}>
          <View style={styles.InputContainer}>
          <Picker
            selectedValue={selectedAnimal}
            style={styles.UserInput}
            onValueChange={(itemValue, itemIndex) =>
              setSelectedAnimal(itemValue)
          }>
            {pickerGenerator(generateList('/Static/Animals'))}
          </Picker>
          </View>
          <Pressable
            style={styles.button}
            android_ripple={{ color: 'white' }}
            onPress={() => {
              console.log(generateList('/Static/Animals'));
          }}>
          <Text style={styles.buttoncontent}>Test</Text>
          </Pressable>
        </View>
      )
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        backgroundColor: '#fff',
        alignItems: 'center',
        justifyContent: 'center',
        marginHorizontal: 8,
      },
      InputContainer: {
        alignSelf: 'stretch',
        marginBottom: 20,
        borderWidth: 1,
        borderStyle: 'solid',
        borderColor: 'darkviolet',
        borderRadius: 4,
      },
      UserInput: {
        fontSize: 16,
        height: 42,
        paddingHorizontal: 8,
      },
      button: {
        alignItems: 'center',
        justifyContent: 'center',
        paddingVertical: 12,
        paddingHorizontal: 32,
        marginVertical: 5,
        borderRadius: 4,
        elevation: 5,
        backgroundColor: 'cornflowerblue',
      },
      buttoncontent: {
        textAlign: 'center',
        fontSize: 16,
        lineHeight: 24,
        fontWeight: 'bold',
        color: 'white',
      },
    });
    
    export default Test;