In my RN.js application, I am struggling to display information on the first time that a page loads. To give a quick background, this application is using Prisma and Axios to pull data from a SQL Server. An axios.get(...)
request is made to pull a list of objects from the database, and then the resp
data is then set to an object that is initialized using a format like setX(resp.data.XList);
. To ensure that the query is only run once the user navigates to the page, I used useEffect(() => {...}, []);
.
What is odd is that the first time a user tries to load this page, they are met with an error since resp.data.XList
prints out in the console as Array []
. If the user then swipes back and navigates to the page for a second time, everything that should load does load.
I believe this is an issue with not having some async
functionality where it is needed, causing the setX(...)
function to be called before the resp
data is returned.
To attempt to resolve this, I have tried to create a function that initializes a Promise object
and delays for 1 second between when.then((resp) ... )
is called and setX(resp.data.XList)
is called. This did not fix it
Another attempt I made was to use a JWT header
to require the get request to check that the user's token (session variable) was still valid in a nice async
way. This helps to verify that some of the code within the get request will run without error. This did not fix it either.
So, without further ado, here are my loadDataOnlyOnce()
and delay()
functions as well as some example UI code: (code has been re-formatted for security reasons. Apologies for not being immediately reproducable)
const [data, setData] = useState([]);
function delay(time)
{
return new Promise(resolve => setTimeout(resolve, time));
}
useEffect(() => {
loadDataOnlyOnce(); //Fires only on first render
}, []);
const loadDataOnlyOnce = () => {
SecureStore.getItemAsync("TOKEN").then(x => {
axios.get(`${baseUrl}/user/pullData`, {
headers: {
'Authorization': `JWT ${x}`
}
}).then((resp) => {
delay(1000).then(() => {
if(resp.data.DataList === undefined){ //Navigates user to page where they can push data to DB. New user wont have any data here.
Alert.alert('Add Data', 'Please Add Data', [
{ text: 'OK', onPress: () => { props.navigation.navigate("AddData")}},
]);
} else{
setData(resp.data.DataList)
console.log(data)
}
});
}).catch((err) => {
Alert.alert('Error', err.response.data.message, [
{ text: 'OK' }
]);
});
});
};
return(
<View>
{data.map(({parameter1, parameter2, id}) => (
<DisplayX parameter1={parameter1} parameter2={parameter2} key={id}/>
))}
</View>
);
Note: data.map
is used to dynamically display the list of objects returned from the get request. <DisplayX ... />
is a component that displays the different parameters of data
Any suggestions would be much appreciated! Thanks!