admin管理员组文章数量:1389825
WebView JavaScript execution started VM11913:31 WebView JavaScript execution started VM11915:31 WebView JavaScript execution started ...
I've tried removing the injected JavaScript code that logs these messages, yet the issue persists. Here are some key points regarding my setup:
State Updates & Navigation:
I update the WebView's source based on a state variable (e.g.,
currentUrl
).In the
onNavigationStateChange
event, I compare the current URL with the new URL.However, even when the URLs are the same (or only differ in minor ways like a trailing slash), the WebView reloads repeatedly.
Injected JavaScript:
The injected JavaScript logs "WebView JavaScript execution started" and sets up event listeners for messages.
Since removing it doesn’t stop the reload, it seems that the code is being re-injected every time the WebView reloads, indicating that the reload is triggered elsewhere.
Other Considerations:
I'm using NetInfo to monitor network state, and some useEffect hooks that might be causing unnecessary re-renders.
I also attempted to normalize the URL before updating the state, but the problem remains.
What I've tried so far:
Removing the injected JavaScript (the reload still occurs).
Using
console.trace()
inonLoadStart
andonNavigationStateChange
to inspect the call stack.Debugging with React Native Debugger, but I still can’t pinpoint the exact trigger.
import React, { useEffect, useRef, useState } from 'react';
import { check, request, PERMISSIONS, RESULTS, openSettings } from 'react-native-permissions';
import PermissionScreen from "./PermissionScreen";
import NoInternetScreen from "./NoInternetScreen.tsx";
import LocationPermissionModal from "./LocationPermissionModal.tsx";
import AsyncStorage from '@react-native-async-storage/async-storage';
import NetInfo from "@react-native-community/netinfo";
import {
ActivityIndicator,
StyleSheet,
BackHandler,
ToastAndroid,
StatusBar,
PermissionsAndroid,
Platform,
Alert,
View,
Text
} from 'react-native';
import { WebView } from 'react-native-webview';
import Geolocation from '@react-native-community/geolocation';
const App: React.FC = () => {
const [isPermissionGranted, setIsPermissionGranted] = useState(false);
const [isWebViewLoaded, setIsWebViewLoaded] = useState(false);
const [isPageLoaded, setIsPageLoaded] = useState(false);
const [isFirstLaunch, setIsFirstLaunch] = useState(true);
const webviewRef = useRef<WebView>(null);
// Replace sensitive URL information with example
const [currentUrl, setCurrentUrl] = useState('/');
const [checkUrl, setCheckUrl] = useState('/');
const [isLocationDenied, setIsLocationDenied] = useState(false);
const [barStyle, setBarStyle] = useState<'dark-content' | 'light-content'>('dark-content');
// Handler for navigation state change
const handleNavigationStateChange = (navState: any) => {
if (!navState) return;
const url = navState;
if (url.includes('mypage') || url.includes('dark-theme')) {
console.log("Detected dark background -> changing status bar text to light");
setBarStyle('light-content');
} else {
console.log("Detected light background -> changing status bar text to dark");
setBarStyle('dark-content');
}
};
const userAgent = (() => {
if (Platform.OS === "ios") {
const iosVersion = parseFloat(Platform.Version.toString());
return iosVersion < 16
? "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1"
: "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1";
}
return "MyAppWebView";
})();
let isLocationSent = false; // To ensure location data is sent only once
const sendLocationToWebView = async () => {
console.log("Requesting location data.");
const granted = await checkLocationPermission();
if (granted !== true) {
console.warn("Location permission denied!");
setIsLocationDenied(true);
const jsCode = `
if (window.receiveLocationFromReactNative) {
window.receiveLocationFromReactNative(${JSON.stringify({
type: "ERROR",
reason: "LOCATION_DENIED"
})});
}
`;
webviewRef.current?.injectJavaScript(jsCode);
return;
}
Geolocation.getCurrentPosition(
(position) => {
const { latitude, longitude } = position.coords;
const locationData = {
type: "LOCATION_DATA",
latitude,
longitude
};
console.log("Location data generated in React Native:", JSON.stringify(locationData));
const jsCode = `
if (window.receiveLocationFromReactNative) {
window.receiveLocationFromReactNative(${JSON.stringify(locationData)});
}
`;
webviewRef.current?.injectJavaScript(jsCode);
setIsLocationDenied(false);
isLocationSent = true;
},
(error) => {
console.warn("Error obtaining location data:", error);
if (Platform.OS === "ios") {
Alert.alert(
"Location Service Needed",
"Please enable location services in your iPhone settings to get your location.",
[{ text: "Go to Settings", onPress: () => openSettings() }, { text: "Cancel", style: "cancel" }]
);
}
setIsLocationDenied(true);
isLocationSent = false;
const jsCode = `
if (window.receiveLocationFromReactNative) {
window.receiveLocationFromReactNative(${JSON.stringify({
type: "ERROR",
reason: "LOCATION_DENIED"
})});
}
`;
webviewRef.current?.injectJavaScript(jsCode);
},
{ enableHighAccuracy: true, timeout: 5000 }
);
};
const [isInternetConnected, setIsInternetConnected] = useState<boolean | null>(true);
useEffect(() => {
console.log('1');
const checkInternet = async () => {
try {
// Send a HEAD request to a public server (e.g., Google) to check for network connectivity
const response = await fetch(";, { method: "HEAD" });
if (response.ok) {
console.log("Internet connection is normal");
setIsInternetConnected(true);
} else {
console.log("Internet connection is down (non-normal response)");
setIsInternetConnected(false);
}
} catch (error) {
console.log("Internet connection is down (request failed)");
setIsInternetConnected(false);
}
};
// Listen for network status changes using NetInfo
const unsubscribe = NetInfo.addEventListener((state) => {
console.log("Detected network state change:", state.isConnected);
if (state.isConnected === false) {
setIsInternetConnected(false);
} else {
checkInternet();
}
});
return () => unsubscribe();
}, []);
const checkNotificationPermission = async () => {
await checkNotifications()
.then((status) => {
setDeviceNotiCheck(status);
})
.catch((error) => console.log('checkNotifications', error));
};
useEffect(() => {
checkNotificationPermission();
}, []);
const hasRequestedPermission = useRef(false);
const checkLocationPermission = async () => {
if (Platform.OS === "ios") {
console.log("Detected iOS environment!");
const status = await check(PERMISSIONS.IOS.LOCATION_WHEN_IN_USE);
console.log("iOS location permission status:", status);
if (status === RESULTS.GRANTED) {
console.log("Location permission is already granted");
return true;
}
if (status === RESULTS.UNAVAILABLE || status === RESULTS.BLOCKED) {
console.warn("Location permission is unavailable or blocked -> treating as LOCATION_DENIED");
return "LOCATION_DENIED";
}
if (status === RESULTS.DENIED) {
if (hasRequestedPermission.current) {
console.warn("Permission already requested, stopping further requests.");
const jsCode = `
if (window.receiveLocationFromReactNative) {
window.receiveLocationFromReactNative(${JSON.stringify({
type: "ERROR",
reason: "LOCATION_ALREADY_REQUESTED"
})});
}
`;
webviewRef.current?.injectJavaScript(jsCode);
return "LOCATION_ALREADY_REQUESTED";
}
console.log("Location permission denied. Requesting again (only once)!");
hasRequestedPermission.current = true;
const newStatus = await request(PERMISSIONS.IOS.LOCATION_WHEN_IN_USE);
console.log("New iOS location permission status:", newStatus);
return newStatus === RESULTS.GRANTED ? true : "LOCATION_DENIED";
}
}
if (Platform.OS === "android") {
const result = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION);
console.log("Android location permission status:", result);
if (result) return true;
if (hasRequestedPermission.current) {
console.warn("Permission already requested, stopping further requests.");
const jsCode = `
if (window.receiveLocationFromReactNative) {
window.receiveLocationFromReactNative(${JSON.stringify({
type: "ERROR",
reason: "LOCATION_ALREADY_REQUESTED"
})});
}
`;
webviewRef.current?.injectJavaScript(jsCode);
return "LOCATION_ALREADY_REQUESTED";
}
hasRequestedPermission.current = true;
const requestResult = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION);
console.log("New Android location permission status:", requestResult);
return requestResult === PermissionsAndroid.RESULTS.GRANTED ? true : "LOCATION_DENIED";
}
console.warn("Running on an unknown platform!");
return false;
};
const handleMessage = async (event: any) => {
const rawMessage = event.nativeEvent.data;
console.log("Received message from WebView: -------------------", rawMessage);
let message;
try {
message = JSON.parse(rawMessage);
} catch (error) {
message = rawMessage; // If JSON parsing fails, use the raw message
}
if (message.type === "LOCATIONERROR" && message.reason === "LOCATION_DENIED") {
console.warn("Location permission denied -> prompting user to go to settings");
return;
}
if (message === "REQ:LOCATION") {
console.log("Received location request from WebView");
const granted = await checkLocationPermission();
if (granted) {
console.log("Location permission granted -> sending location data");
sendLocationToWebView();
} else {
console.warn("Location permission denied -> displaying settings modal");
const jsCode = `
if (window.receiveLocationFromReactNative) {
window.receiveLocationFromReactNative(${JSON.stringify({
type: "ERROR",
reason: "LOCATION_DENIED"
})});
}
`;
webviewRef.current?.injectJavaScript(jsCode);
setIsLocationDenied(true);
}
} else if (typeof message === "string" && message.startsWith(";)) {
console.log("Received Kakao auth URL. Opening in WebView");
setCurrentUrl(message);
} else if (typeof message === "string" && message.startsWith(";)) {
console.log("Received Naver auth URL. Opening in WebView");
setCurrentUrl(message);
} else if (typeof message === "string" && message.startsWith(";)) {
console.log("Received Google auth URL. Opening in WebView");
setCurrentUrl(message);
} else if (typeof message === "string" && message.startsWith(";)) {
console.log("Received Apple auth URL. Opening in WebView");
setCurrentUrl(message);
} else if (message === 'REQ:LOGIN') {
console.log("Received login request from WebView");
initiateKakaoLogin();
} else if (typeof message === "object" && message.type === "REQ:PASS_AUTH") {
console.log("Received REQ:PASS_AUTH message:", message);
await initiatePassAuth(message.token);
} else if (typeof message === "object" && message.type === "APPLE_LOGIN" && message.status === "FAILED") {
console.error("Detected Apple login failure:", message);
Alert.alert("Login Error", "Apple login failed. Please try again.");
setTimeout(() => {
webviewRef.current?.injectJavaScript(`window.location.href = '/'`);
}, 2000);
} else {
console.log("Unknown message:", message);
}
};
const initiatePassAuth = async (token: string) => {
try {
const apiUrl = ";;
const response = await fetch(apiUrl, {
method: "POST",
headers: {
Authorization: token,
"Content-Type": "application/json",
},
});
if (response.ok) {
const data = await response.json();
console.log("PASS API response successful:", data);
const { enc_data, integrity_value, token_version_id } = data.context;
const message = {
type: "PASS_AUTH_SUCCESS",
data: { enc_data, integrity_value, token_version_id },
};
if (webviewRef.current) {
webviewRef.current.postMessage(JSON.stringify(message));
console.log("Sent PASS data to WebView:", message);
} else {
console.error("WebView is not ready.");
}
} else {
console.error("PASS API response failed:", response.status);
}
} catch (error) {
console.error("Error during PASS API call:", error);
}
};
const initiateKakaoLogin = () => {
const kakaoAuthUrl = ``;
fetch(kakaoAuthUrl, { method: 'GET' })
.then(response => response.json())
.then(data => {
console.log("Login successful:", data);
const jsCode = `
window.handleLoginSuccess && window.handleLoginSuccess(${JSON.stringify(data)});
`;
webviewRef.current?.injectJavaScript(jsCode);
})
.catch(error => {
console.error("Error during login request:", error);
Alert.alert("Login Error", "There was a problem with the login request.");
});
};
const [backPressCount, setBackPressCount] = useState(0);
const [canGoBack, setCanGoBack] = useState(false);
useEffect(() => {
const backAction = () => {
if (backPressCount === 0) {
webviewRef.current.goBack();
setBackPressCount(1);
ToastAndroid.show("Press back again to exit.", ToastAndroid.SHORT);
setTimeout(() => setBackPressCount(0), 2000);
return true;
}
if (backPressCount === 1) {
BackHandler.exitApp();
return true;
}
return false;
};
const backHandler = BackHandler.addEventListener("hardwareBackPress", backAction);
return () => backHandler.remove();
}, [backPressCount, canGoBack]);
const handleOAuthRedirect = async (url: string) => {
console.log("Detected OAuth Redirect:", url);
if (url.startsWith(";)) {
console.log("SNS login completion URL detected!");
const params = new URL(url).searchParams;
const encodedData = params.get("data");
if (encodedData) {
const decodedData = decodeURIComponent(encodedData);
console.log("OAuth login success data:", decodedData);
const jsCode = `
if (window.handleOAuthSuccess) {
window.handleOAuthSuccess(${decodedData});
}
`;
webviewRef.current?.injectJavaScript(jsCode);
}
}
};
const [shouldUseSafeArea, setShouldUseSafeArea] = useState(false);
useEffect(() => {
console.log("Detected current URL change:", currentUrl);
const safeUrls = [
";,
";,
";,
"/",
";,
";,
";
];
const isSafe = safeUrls.some(pattern => checkUrl.includes(pattern));
console.log("Applying Safe Area:", isSafe);
setShouldUseSafeArea(isSafe);
}, [checkUrl]);
useEffect(() => {
checkFirstLaunch();
}, []);
const checkFirstLaunch = async () => {
const firstLaunch = await AsyncStorage.getItem("first_launch");
if (firstLaunch === "done") {
setIsFirstLaunch(false);
} else {
setIsFirstLaunch(true);
}
};
const handlePermissionsGranted = async () => {
console.log("isFirstLaunch", isFirstLaunch);
await AsyncStorage.setItem("first_launch", "done");
setIsFirstLaunch(false);
};
const clearWebViewCache = () => {
if (webviewRef.current) {
webviewRef.current.clearCache(true);
console.log("WebView cache cleared!");
}
};
const prevNavState = useRef<string | null>(null);
return (
<View style={[styles.container, shouldUseSafeArea && styles.safeAreaContainer]}>
<StatusBar
hidden={false}
translucent={true}
backgroundColor="transparent"
barStyle={barStyle}
/>
{(!isWebViewLoaded || !isPageLoaded) && (
<View style={styles.splashScreen}>
<ActivityIndicator size="large" color="#0000ff" />
</View>
)}
{isInternetConnected === true ? (
isFirstLaunch === true ? (
<PermissionScreen onPermissionsGranted={handlePermissionsGranted} />
) : (
<>
{isLocationDenied === true && (
<LocationPermissionModal
visible={isLocationDenied}
onClose={() => setIsLocationDenied(false)}
/>
)}
<WebView
onLoadStart={() => {
console.log("
本文标签:
reactjsInfinite Reloading of React Native WebView – How to Trace the TriggerStack Overflow
版权声明:本文标题:reactjs - Infinite Reloading of React Native WebView – How to Trace the Trigger? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人,
转载请联系作者并注明出处:http://www.betaflare.com/web/1744655891a2617962.html,
本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论