Home > Back-end >  React native with expo app rendering an empty page with no errors
React native with expo app rendering an empty page with no errors

Time:11-04

I have no errors showing but I am getting a blank page when my app runs. It started rendering a blank page when started putting some api code which I copied and pasted from another project where it worked exactly perfect but for some reason, it is refusing to work here This is how my code looks like. This is my App.js file

import React from 'react'
import { StyleSheet, Text, View } from 'react-native'
import Screen from './app/components/Screen'
import ProductScreen from './app/screens/ProductScreen';

export default function App() {

  return (
    <Screen>
      <ProductScreen />
    </Screen>
  )
}

Then this is the product screen.js

import React, {useState, useEffect} from 'react'
import { FlatList, StyleSheet, ActivityIndicator, Text, View } from 'react-native'
import Card from '../components/Card';

export default function ProductScreen() {
    const [products, setproducts] = useState([]);
    const [loading, setloading] = useState(true);

    const getProducts = async () => {
        try {
            const response = await fetch('https://fakestoreapi.com/products/1');
            const data = await response.json();
            setproducts(data);
        } catch (error) {
            console.log("Something went wrong in your code",error)
        } finally {
            setloading(false);
        }
    }

    useEffect(() => {
        getProducts();
    }, []);

    return (
        <View>
           {loading ? <ActivityIndicator/> : (
               <FlatList
                   data={products}
                   keyExtractor={(id) => id}
                   renderItem={({item}) => (
                       <Card 
                           title={item.title}
                           subtitle={item.description}
                           img={item.image}
                       />
                   )}
               />
           )}
        </View>
    )
}

const styles = StyleSheet.create({})

And lastly the card.js file

import { Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native'
import AppText from './AppText';

export default function Card({title, subtitle, img}) {
    return (
        <View style={styles.container}>
            <Image source={img} style={styles.image} />
            <View style={styles.cardText}>
                <AppText style={{color: "black"}}>{title}</AppText>
                <AppText style={{color: "#4ecdc4"}}>{subtitle}</AppText>
            </View>
        </View>
    )
}

Where could I be going wrong?

CodePudding user response:

Well there are several issues in your Expo Snack. First your expression of:

{loading && <FlatList />}

is wrong because you're setting it to check for loading of true when after you retrieve your data in getProducts you set it to false.

Was able to get it to work, again, with:

import React, { useState, useEffect } from 'react'
import { FlatList, StyleSheet, View } from 'react-native'
import Card from '../components/Card'

export default function ProductScreen() {
  const [products, setProducts] = useState([])
  const [loading, setLoading] = useState(true)

  const getProducts = async () => {
    try {
      const response = await fetch('https://fakestoreapi.com/products/5')
      const data = await response.json()
      setProducts([data])
      setLoading(false)
    } catch (error) {
      console.log('Something went wrong in your code', error)
    }
  }

  useEffect(() => {
    getProducts()
  }, [])

  return (
    <View style={styles.container}>
      {!loading && products.length !== 0 && (
        <View>
          <FlatList
            data={products}
            keyExtractor={(_, id) => id.toString()}
            renderItem={({ item }) => <Card title={item.title} subtitle={item.description} img={item.image} />}
          />
        </View>
      )}
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    backgroundColor: 'lightgrey',
    flex: 1,
  },
})

Another error exists in Card for Image. Per memory when passing an image URL it should be set with a URI:

<Image source={{ uri: img }} style={styles.image} />

Another issue you'll face is in ProductScreen the View style for container should have a flex: 1 applied as indicated in the code above.

CodePudding user response:

Looking at the code for snack.expo.dev/@vuyi/spontaneous-candy it seems your missing the conditional rendering in your return for the ProductScreen.

Your code looks like this:

<View style={styles.container}>
           {loading &&
               <FlatList
                   data={[products]}
                   keyExtractor={(_, id) => id.toString()}
                   renderItem={({item}) => 
                       <Card 
                           title={item.title}
                           subtitle={item.description}
                           img={item.image}
                       />
                   }
               />
           }
        </View>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

When it needs to look something like this:

 <View style={styles.container}>
           {loading ? null :
               <FlatList
                   data={[products]}
                   keyExtractor={(_, id) => id.toString()}
                   renderItem={({item}) => 
                       <Card 
                           title={item.title}
                           subtitle={item.description}
                           img={item.image}
                       />
                   }
               />
           }
        </View>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Adding that conditional will prevent your Flatlist component from rendering before it has access to the data you are fetching. It looks like you had it right in the original post but not in the Expo Snack environment.

  • Related