I have a react native project I am working on. There are two screens. One screen is a list of properties and details that render based on an api call to zillows api. When a property is clicked on, I want it to go to a different screen with the zpid that is passed to the new screen.
On the new screen, I have two states that are set. I have a loading state that is set to true. loading will be set to true until the new api call is made and until the loading state is set to false, I want to screen to render loading text. Once the loading is set to false and the property state is set to the results of the api call, I want to render the property details on the screen.
My issue right now is that I have a useEffect right now that runs the zillow api call right when the screen loads. Once the results are stored in the property state, I set the loading to false.
When this happens I am getting an undefined variable issue that is suppsed to render the property price from the property state. I know that the issue is caused when it is trying to grab from the property state before it is loaded but I am not sure how to delay rendering the content until after the property state is set.
component:
import React, { useState, useEffect } from 'react'
import { Dimensions } from 'react-native'
import { View, Image, Text, StyleSheet, FlatList, TextInput, Button } from 'react-native'
import { ScrollView } from 'react-native-gesture-handler'
import { propertyOptions } from '../api/zillowApi'
import { convertToDollars } from '../utilities'
import axios from 'axios';
const PropertyDetail = (props) => {
const {
route
} = props
const [property, setProperty] = useState()
const [loading, setLoading] = useState(true)
let zpid = route.params.zpid
let deviceWidth = Dimensions.get('window').width
var aspectHeight = (deviceWidth / 1.78) 1
let carouselImageWidth = (deviceWidth / 4)
let carouselImageHeight = (carouselImageWidth / 1.78)
let options = propertyOptions
options.params.zpid = zpid
useEffect(() => {
axios.request(options)
.then(function (response) {
// console.log("single property: ", response.data);
setProperty(response)
setLoading(false)
}).catch(function (error) {
console.error(error);
});
}, [])
const loadingContent = <Text>Loading</Text>
const loadedContent = <ScrollView>
<View style={styles.imagesContainer} className="images-container">
<View style={[styles.mainImageContainer,{height: aspectHeight}]} className="main-image-container">
<Image style={styles.mainImage} source={{uri: property.data.imgSrc}}/>
</View>
<View style={styles.carouselContainer} className="image-carousel-image">
<FlatList
horizontal
data={carouselImages}
renderItem={({item}) => <Image style={{height: carouselImageHeight, width:carouselImageWidth}} source={require('../../assets/luxury-home-1.jpeg')}/>}
/>
</View>
</View>
...
<View style={styles.taxHistoryContainer}>
<View style={styles.contactContainer}>
<Text>Listing Agent: Omar Jandali (DRE# 02151051)</Text>
<Text>Listing Brokerage: Compass (DRE# 00132433)</Text>
</View>
<View style={styles.expense}>
<TextInput placeholder='First Name'/>
<TextInput placeholder='Last Name'/>
</View>
<View style={styles.expense}>
<TextInput placeholder='Subject'/>
</View>
<View style={styles.expense}>
<TextInput placeholder='Message'/>
</View>
<Button title='Submit'/>
</View>
</ScrollView>
return(
<View>
{
loading == true ? loadingContent : loadedContent
}
</View>
)
}
I want to delay rendering the content until I know that the property state is set and I dont know how to do that...
CodePudding user response:
You can do an early return, below the useEffect and your components.
(sorry if the component names are different).
if (!property) return <LoadingContent />
return (
<View>
<LoadedContent />
</View>
)
Also, you should set your loading
to false in the useState
.
Then when making your axios
call, set it to true.
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
try {
const res = await axios.request(options);
if (res) {
setProperty(res.data);
}
} catch ...
finally {
setLoading(false);
}
}, [])
on another note, is there a reason why the initial value of your property
state value is nothing? I normally would set it to null
, so it's definite that it's false if there is no update to that state.