My react native expo iOS app is working totally although expo. Sadly, when doing a growth construct, or via take a look at flight I get a white display screen. I’m struggling to debug this as inside TestFlight I’ve no entry to the console.
I’m able to zoom out and in (as indicated by the scroll bars showing), nevertheless your complete content material is a plain white display screen.
My normal workflow to get onto TestFlight is listed under:
npx expo prebuild
eas construct –platform ios
eas submit -p ios –latest
No console or construct errors in expo, so fairly tough to debug.
Any assist right here can be enormously appreciated!
import React, { useRef } from 'react';
import { View, StyleSheet, StatusBar } from 'react-native';
import { WebView } from 'react-native-webview';
import * as FileSystem from 'expo-file-system';
import * as MediaLibrary from 'expo-media-library';
import * as Clipboard from 'expo-clipboard';
import * as Sharing from 'expo-sharing';
import { script } from './property/constants';
const HTML_CONTENT = require('./property/physique.html');
export default operate App() {
const webViewRef = useRef(null);
const kinds = StyleSheet.create({
container: {
flex: 1,
},
webView: {
flex: 1,
},
});
const handleMessage = async (occasion) => {
const message = JSON.parse(occasion.nativeEvent.knowledge);
console.log('Message from WebView:', message);
change (message.sort) {
case 'copyToClipboard':
attempt {
await Clipboard.setStringAsync(message.knowledge);
webViewRef.present.injectJavaScript(`
window.dispatchEvent(new MessageEvent('message', {
knowledge: JSON.stringify({ sort: 'clipboardResponse', success: true })
}));
true;
`);
} catch (error) {
console.error('Error copying to clipboard:', error);
webViewRef.present.injectJavaScript(`
window.dispatchEvent(new MessageEvent('message', {
knowledge: JSON.stringify({
sort: 'clipboardResponse',
success: false,
error: ${JSON.stringify(error.message)}
})
}));
true;
`);
}
break;
case 'log':
console.log('WebView log:', message.message);
break;
case 'error':
console.error('WebView error:', message.message);
break;
case 'exportPNG':
attempt {
const { standing } = await MediaLibrary.requestPermissionsAsync();
if (standing === 'granted') {
const filename = FileSystem.documentDirectory + 'color_palette.png';
await FileSystem.writeAsStringAsync(filename, message.knowledge.break up(',')[1], { encoding: FileSystem.EncodingType.Base64 });
await MediaLibrary.saveToLibraryAsync(filename);
// Ship success message again to WebView
webViewRef.present.injectJavaScript(`
window.dispatchEvent(new MessageEvent('message', {
knowledge: JSON.stringify({ sort: 'exportSuccess' })
}));
// Reset button textual content
doc.getElementById('exportPngBtn').textContent="Export to PNG";
true;
`);
} else {
webViewRef.present.injectJavaScript(`
window.dispatchEvent(new MessageEvent('message', {
knowledge: JSON.stringify({ sort: 'exportError', error: 'Permission denied' })
}));
doc.getElementById('exportPngBtn').textContent="Export to PNG";
true;
`);
}
} catch (error) {
console.error('Error saving picture:', error);
webViewRef.present.injectJavaScript(`
window.dispatchEvent(new MessageEvent('message', {
knowledge: JSON.stringify({ sort: 'exportError', error: ${JSON.stringify(error.message)} })
}));
doc.getElementById('exportPngBtn').textContent="Export to PNG";
true;
`);
}
break;
case 'exportProcreate':
attempt {
const { standing } = await MediaLibrary.requestPermissionsAsync();
if (standing === 'granted') {
const timestamp = Date.now();
const tempDir = FileSystem.cacheDirectory;
const acoPath = `${tempDir}my_palette.aco`;
await FileSystem.writeAsStringAsync(
acoPath,
message.knowledge.aco,
{ encoding: FileSystem.EncodingType.Base64 }
);
await Sharing.shareAsync(acoPath, {
mimeType: 'software/octet-stream',
dialogTitle: 'Save Shade Palette',
UTI: 'public.knowledge',
filename: 'my_palette.aco' // Set default filename for sharing
});
attempt {
await FileSystem.deleteAsync(acoPath);
} catch (cleanupError) {
console.warn('Cleanup error:', cleanupError);
}
webViewRef.present.injectJavaScript(`
window.dispatchEvent(new MessageEvent('message', {
knowledge: JSON.stringify({ sort: 'exportSuccess' })
}));
doc.getElementById('exportProcreateBtn').textContent="Export to Procreate";
true;
`);
}
} catch (error) {
console.error('Error saving palette file:', error);
webViewRef.present.injectJavaScript(`
window.dispatchEvent(new MessageEvent('message', {
knowledge: JSON.stringify({
sort: 'exportError',
error: ${JSON.stringify(error.message)}
})
}));
doc.getElementById('exportProcreateBtn').textContent="Export to Procreate";
true;
`);
}
break;
default:
console.warn('Unknown message sort from WebView:', message.sort);
}
};
const injectedJavaScript = `
console = {
log: operate(message) {
window.ReactNativeWebView.postMessage(JSON.stringify({sort: 'log', message: message}));
},
error: operate(message) {
window.ReactNativeWebView.postMessage(JSON.stringify({sort: 'error', message: message}));
}
};
${script}
`;
return (
);
}