I am trying to deploy an minimalistic app using expo (and react native). I have set up a splash screen and 4 other screens. Everything works fine when running expo start
(both on ios and android). However when i try to create an dev build, eas build -p ios --profile preview
, the build runs perfectly but when the app starts i see the splash screen then a white screen. Here are the important files:
{
"name": "apotheca",
"version": "1.0.0",
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web"
},
"dependencies": {
"@react-navigation/bottom-tabs": "^6.5.7",
"@react-navigation/native": "^6.1.6",
"@react-navigation/stack": "^6.3.16",
"expo": "~48.0.15",
"expo-file-system": "^15.2.2",
"expo-font": "^11.1.1",
"expo-secure-store": "^12.1.1",
"expo-splash-screen": "^0.18.2",
"expo-sqlite": "^11.1.1",
"expo-status-bar": "~1.4.4",
"expo-updates": "^0.16.4",
"path": "^0.12.7",
"react": "18.2.0",
"react-native": "0.71.7",
"react-native-screens": "^3.20.0"
},
"devDependencies": {
"@babel/core": "^7.20.0"
},
"private": true
}
the App.js
import React, {useEffect, useState} from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Image } from 'react-native';
import { useFonts } from 'expo-font';
import * as FileSystem from 'expo-file-system';
import * as SQLite from 'expo-sqlite';
import * as SecureStore from 'expo-secure-store';
import { Modal, Pressable } from 'react-native';
import PlantsSearchScreen from './screens/plantsSearch';
import PlantDetailsScreen from './screens/plantsDetails';
import PropertiesSearchScreen from './screens/propertiesSearch';
import PropertyDetailsScreen from './screens/propertyDetails';
import { SafeAreaView } from 'react-native';
const Tab = createBottomTabNavigator();
const PlantStack = createStackNavigator();
const PropertyStack = createStackNavigator();
const PlantsStackNavigator = () => {
return (
<PlantStack.Navigator>
<PlantStack.Screen name="Plants"
component={PlantsSearchScreen}
options={{
headerShown: true,
headerTitleStyle: {
fontFamily: 'CaslonAntique',
fontSize: 30,
},
headerStyle: { backgroundColor: '#e2cca7' },
}}
/>
<PlantStack.Screen name="Plant Details"
component={PlantDetailsScreen}
options={{
headerShown: true,
headerTitleStyle: {
fontFamily: 'CaslonAntique',
fontSize: 30,
},
headerBackTitle: 'Back',
headerBackTitleStyle: {
fontFamily: 'CaslonAntique',
fontSize: 20,
},
headerStyle: { backgroundColor: '#e2cca7' },
}}
/>
<PlantStack.Screen name="Property Details"
component={PropertyDetailsScreen}
options={{
headerShown: true,
headerTitleStyle: {
fontFamily: 'CaslonAntique',
fontSize: 30,
},
headerBackTitle: 'Back',
headerBackTitleStyle: {
fontFamily: 'CaslonAntique',
fontSize: 20,
},
headerStyle: { backgroundColor: '#e2cca7' },
}}
/>
</PlantStack.Navigator>
);
};
const PropertiesStackNavigator = () => {
return (
<PropertyStack.Navigator>
<PropertyStack.Screen name="Properties"
component={PropertiesSearchScreen}
options={{
headerShown: true,
headerTitleStyle: {
fontFamily: 'CaslonAntique',
fontSize: 30,
},
headerStyle: { backgroundColor: '#e2cca7' },
}}
/>
<PropertyStack.Screen name="Property Details"
component={PropertyDetailsScreen}
options={{
headerShown: true,
headerTitleStyle: {
fontFamily: 'CaslonAntique',
fontSize: 30,
},
headerBackTitle: 'Back',
headerBackTitleStyle: {
fontFamily: 'CaslonAntique',
fontSize: 20,
},
headerStyle: { backgroundColor: '#e2cca7' },
}}
/>
<PropertyStack.Screen name="Plant Details"
component={PlantDetailsScreen}
options={{
headerShown: true,
headerTitleStyle: {
fontFamily: 'CaslonAntique',
fontSize: 30,
},
headerBackTitle: 'Back',
headerBackTitleStyle: {
fontFamily: 'CaslonAntique',
fontSize: 20,
},
headerStyle: { backgroundColor: '#e2cca7' },
}}
/>
</PropertyStack.Navigator>
);
};
const App = () => {
const [modalVisible, setModalVisible] = useState(true);
const [fontLoadTimeout, setFontLoadTimeout] = useState(false);
const handleUnderstoodPress = () => {
setModalVisible(false);
};
const [fontsLoaded] = useFonts({
'CaslonAntique': require('./assets/fonts/CaslonAntique.ttf'),
'CaslonAntique-Bold': require('./assets/fonts/CaslonAntique-Bold.ttf'),
'CaslonAntique-Italic': require('./assets/fonts/CaslonAntique-Italic.ttf'),
});
useEffect(() => {
const timer = setTimeout(() => {
setFontLoadTimeout(true);
}, 10000); // Set a 10-second timeout
return () => clearTimeout(timer);
}, []);
if (!fontsLoaded) {
if (fontLoadTimeout) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Error loading fonts. Please restart the app or check your internet connection.</Text>
</View>
);
}
return <View />;
}
return (
<SafeAreaView style={{ flex: 1, backgroundColor: '#e2cca7' }}>
<View style={styles.container}>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Text style={styles.modalText}>
Disclaimer: This app is intended for informational purposes only and should not be used as a substitute for professional medical advice. Always consult a healthcare professional if you have any concerns or doubts. The posology information provided in this app is not a medical recommendation and may be harmful if used without proper guidance from a healthcare professional.
</Text>
<Pressable
style={[styles.button, styles.buttonClose]}
onPress={handleUnderstoodPress}
>
<Text style={styles.textStyle}>Understood</Text>
</Pressable>
</View>
</View>
</Modal>
<NavigationContainer>
<Tab.Navigator
screenOptions={{tabBarLabelStyle: {fontFamily: 'CaslonAntique', fontSize: 20},
tabBarStyle: { backgroundColor: '#e2cca7' ,
borderTopWidth: 2, // Add this line to create a black line above the bottom bar
paddingTop: 10,
borderTopColor: 'black' // Add this line to set the line color to black
},
tabBarActiveTintColor: '#222222',
headerShown: false,}}
>
<Tab.Screen
name="PlantsTab"
component={PlantsStackNavigator}
options={{
title: '', // Set this to an empty string
tabBarLabel: 'Plants',
tabBarIcon: ({ focused, color, size }) => (
<Image
source={require('./assets/plant-icon.png')}
style={{ width: size, height: size, tintColor: color }}
/>
),
}}
/>
<Tab.Screen
name="PropertiesTab"
component={PropertiesStackNavigator}
options={{
title: '', // Set this to an empty string
tabBarLabel: 'Properties',
tabBarIcon: ({ focused, color, size }) => (
<Image
source={require('./assets/mortar.png')}
style={{ width: size, height: size, tintColor: color }}
/>
),
}}
/>
</Tab.Navigator>
</NavigationContainer>
</View>
</SafeAreaView>
);
};
I am wondering if the loading of the fonts can get stuck and prevent the screen from loading? otherwise I have a standard app.json
{
"expo": {
"name": "Apotheca",
"slug": "Apotheca",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"userInterfaceStyle": "light",
"splash": {
"image": "./assets/apothecarySplash.png",
"resizeMode": "contain",
"backgroundColor": "#e2cca7"
},
"assetBundlePatterns": [
"**/*"
],
"ios": {
"supportsTablet": true,
"bundleIdentifier": "com.compagnyName.Apotheca"
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/icon.png",
"backgroundColor": "#e2cca7"
}
},
"extra": {
"eas": {
"projectId": "...."
}
}
}
}
I looked for the xcode logs, build logs, change some parts of the code but nothing seems to help. What could be the issue? (note i have the same issue on android where it is stuck on splashscreen)