Home > database >  React Native getting Firebase data only return "object Object"?
React Native getting Firebase data only return "object Object"?

Time:09-12

I'm facing a problem for a few days now and I might not be able to see the forest because of all the trees (I hope that German saying works in English as well ^^).

I'm building an app for cooking receipes to learn React Native. The app has an overview with the receipes, you can click on one and it forwards the id of that receipe to a detail screen. In that detail screen, I'm getting the data for that specific receipe the same way I do on the overview screen. But - while the overview screen works fine, the detail screen does not - the const [ receipes, setReceipes ] = useState({}) returns [object Object].

This is what I use on the overview screen to get my data:

  { /* functions to handle the receipe data stuff */ }
  const [ receipes, setReceipes ] = useState({});

  const [ presentTitle, setPresentTitle ] = useState('');
  const [ presentIngredients, setPresentIngredients ] = useState([]);
  const [ presentIngredient, setPresentIngredient ] = useState('');
  const [ presentHowTo, setPresentHowTo ] = useState('');
  const receipeKeys = Object.keys(receipes)

  { /* function to make a user write to their subdirectory in the database */ }
  const auth = getAuth()
  const userUID = auth.currentUser?.uid
  const databasePath = userUID '/receipes'

  useEffect(() => {
    return onValue(ref(db, databasePath), querySnapshot => {
      let data = querySnapshot.val() || {};
      let receipeItems = {...data};
      setReceipes(receipeItems);

      console.log('ReceipeScreen | setReceipes = ', receipeItems)
    })
  }, [])

And how I forward it to the details screen:

{ /* main scroll view def */ }
  <ScrollView>
    {receipeKeys.length > 0 ? (
      receipeKeys.map(key => (

        // links to the matching detail screen, passing along the key of the receipe
        <TouchableOpacity
          key = {key}
          onPress={() => navigation.navigate('ReceipeDetailsScreen', key )} >
          <ReceipeItem
            key = {key}
            id = {key}
            receipe = {receipes[key]}
          />
          
        </TouchableOpacity>
      ))
    ) : (
      <Text>No receipes present.</Text>
    )}
  </ScrollView>

Here's the code I use on my detail screen to get my data (note the route props I'm using to then set my databasePath):

const ReceipeDetailScreen = ({ route }) => {

    const navigation = useNavigation();

    const [ receipes, setReceipes ] = useState({});

    { /* function to make a user write to their subdirectory in the database */ }
    const auth = getAuth()
    const userUID = auth.currentUser?.uid

    const currentReceipeID = route.params;
    const databasePath = userUID '/receipes/' currentReceipeID
    
    console.log("ReceipeDetailScreen.js | DatabasePath = "   databasePath)
    
    { /* working with the receipes data */}   
    useEffect(() => {
        return onValue(ref(db, databasePath), querySnapshot => {
            let data = querySnapshot.val() || {};
            let receipeData = {...data};
            setReceipes(receipeData);

            console.log('ReceipeDetailScreen.js | setReceipe = ', receipeData)
        })
    }, []) 

    console.log("ReceipeDetailScreen.js | receipe = "   receipes)

}

Unfortunately, this is what it looks when I'm printing it to the console: enter image description here

Any help on how to fix that would be much appreciated, thanks!

CodePudding user response:

[object Object] is a way of displaying object in the console but this doesn't realy gives you information about the object itself.

You can try using JSON.stringify() to be able to see the content of your object in the console, you can use it this way : console.log('ReceipeDetailScreen.js | setReceipe = ', json.stringify(receipeData))

It might help you understand what's going on.


Edit due to new comment:

Considering that the object is empty I suppose that the method that you're using to get a single reciepe does not work properly, or maybe that your id is wrong?

A temporary fix could be to get the array and then filter it ot only get the reciepe that you want (not exactly clean code)

const ReceipeDetailScreen = ({ route }) => {

const navigation = useNavigation();

const [ receipes, setReceipes ] = useState({});

{ /* function to make a user write to their subdirectory in the database */ }
const auth = getAuth()
const userUID = auth.currentUser?.uid

const currentReceipeID = route.params;
const databasePath = userUID '/receipes/';  // Remove id here

console.log("ReceipeDetailScreen.js | DatabasePath = "   databasePath)

{ /* working with the receipes data */}   
useEffect(() => {
    return onValue(ref(db, databasePath), querySnapshot => {
        let data = querySnapshot.val() || {};
        let receipeData = {...data};
        const receipe = receipeData.find(elt => elt.id === currentReceipeID ) // Search receipe here 
        if(receipe !== undefined){ 
           setReceipes(receipe); 
        }
        console.log('ReceipeDetailScreen.js | setReceipe = ', receipeData)
    })
}, []) 

console.log("ReceipeDetailScreen.js | receipe = "   receipes)

}

CodePudding user response:

I figured out a way how to do this, just in case someone has the same problem.

Instead of writing the data in useEffect to receipeData, I switched over to generating a list of the items keys in here. That way I can iterate over the list of keys and get the data for the matching key.

Let me show you what I mean:

Getting the data:

  const [ receipes, setReceipes ] = useState({});
  const [ presentIngredients, setPresentIngredients ] = useState({});
  const [ presentIngredient, setPresentIngredient ] = useState('');

  const ingredientsKeys = Object.keys(presentIngredients);

  { /* updates "receipes" and "presentIngredients", so we can get their keys 
  and use them to iterate over the objects */ }
  useEffect(() => {
    return onValue(ref(db, databasePath), querySnapshot => {
      let data = querySnapshot.val() || {};
      let receipeItems = {...data};
      setReceipes(receipeItems);
    }),

    onValue(ref( db, databasePathIngredients), querySnapshot => {
        let data = querySnapshot.val() || [];
        let ingresItems = {...data};
        setPresentIngredients(ingresItems);
    })
  }, [])

And then calling a custom item and forwarding the data:

 <View style={styles.ingredientsWrapper}>
      {ingredientsKeys.length > 0 ? (
      ingredientsKeys.map(key => (
        
        <Ingredients
            id={key}
            ingredients={presentIngredients[key]}
        />
        ))
      ) : (
        <Text style={styles.text}>Nothing there, please add something.</Text>
      )}
    </View>
  • Related