I am trying to develop an OpenLayers application using react native.I have 2 projects.The first one has 2 JS functions that i want to call inside the react native project using the WebView component. I've tried working with the injectJavaScript method but it won't work at all.
import { useAssets } from "expo-asset";
import { useContext, useEffect, useRef, useState } from "react";
import { useWindowDimensions } from "react-native";
import WebView from "react-native-webview";
import { Context } from "../App";
const Page = () => {
const [assets] = useAssets([require("../assets/index.html")]);
const [htmlString, setHtmlString] = useState<string>();
const pageDimensions = useWindowDimensions();
const webViewRef = useRef<WebView | null>(null);
const [add, setAdd, swch] = useContext(Context);
useEffect(() => {
if (assets) {
fetch(assets[0].localUri || "")
.then((res) => res.text())
.then((html) => setHtmlString(html));
}
}, [assets]);
useEffect(() => {
if (webViewRef.current) {
console.log(swch)
const functionToCall = swch ? "showMiddlemarker();" : "hideMiddlemarker();";
webViewRef.current.injectJavaScript(`${functionToCall}; true;`);
}
}, [swch]);
if (!htmlString) {
return null;
}
return (
<WebView
ref={(r) => (webViewRef.current = r)}
javaScriptEnabled
source={{
html: htmlString,
}}
style={{
width: pageDimensions.width,
height: pageDimensions.height,
}}
scrollEnabled={false}
overScrollMode="never"
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
scalesPageToFit={false}
containerStyle={{ flex: 1 }}
onLoad={() => {
webViewRef.current?.injectJavaScript(`
function showMiddlemarker() {
console.log("Showing marker");
markerElement.style.display = "block";
}
function hideMiddlemarker() {
console.log("Hiding marker");
markerElement.style.display = "none";
}
true;
`);
}}
/>
);
};
export default Page;
This is the component that loads the built HTML with the map. As you can see, I have tried loading the functions inside onLoad(). The swch variable should control the behavior of the marker. I've checked it's state and it changes when i press the button from true to false correctly.
import "./style.css"
import Feature from 'ol/Feature.js';
import Map from 'ol/Map.js';
import Overlay from 'ol/Overlay.js';
import Point from 'ol/geom/Point.js';
import View from 'ol/View.js';
import {Icon, Style} from 'ol/style.js';
import {OGCMapTile, OSM, Vector as VectorSource} from 'ol/source.js';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer.js';
import { fromLonLat } from 'ol/proj';
const coords = fromLonLat([25.91667,47.85])
const map = new Map({
target: 'map',
layers: [
new TileLayer({
source: new OSM(),
}),
],
view: new View({
center: coords,
zoom: 13,
}),
});
const marker = new VectorLayer({
source: new VectorSource({
features:[
new Feature({
geometry: new Point(
coords
)
})
]
}),
style: new Style({
image: new Icon({
src:".png",
scale:0.07
})
})
})
const markerElement = document.createElement("div");
markerElement.className = "marker";
markerElement.style.width = "32px";
markerElement.style.height = "32px";
markerElement.style.backgroundImage = "url('.png')";
markerElement.style.backgroundSize = "contain";
markerElement.style.position = "absolute";
markerElement.style.transform = "translate(-50%, -50%)";
markerElement.style.display = "block"
const markerOverlay = new Overlay({
element: markerElement,
positioning: "center-center",
stopEvent: false,
});
map.addOverlay(markerOverlay);
map.getView().on("change:center", () => {
const center = map.getView().getCenter();
markerOverlay.setPosition(center);
});
markerOverlay.setPosition(coords);
//map.addLayer(marker)
function hideMiddlemarker() {
markerElement.style.display = "none";
}
function showMiddlemarker() {
markerElement.style.display = "block";
}
Here is the JS project with the map. I'm trying to call showMiddlemarker and hideMiddlemarker inside the react native app but it won't work at all. I've also checked if the webview is loading beforehand. Tried the onMessage method and it works, but the injectJavascript wont run those 2 functions.
I am trying to develop an OpenLayers application using react native.I have 2 projects.The first one has 2 JS functions that i want to call inside the react native project using the WebView component. I've tried working with the injectJavaScript method but it won't work at all.
import { useAssets } from "expo-asset";
import { useContext, useEffect, useRef, useState } from "react";
import { useWindowDimensions } from "react-native";
import WebView from "react-native-webview";
import { Context } from "../App";
const Page = () => {
const [assets] = useAssets([require("../assets/index.html")]);
const [htmlString, setHtmlString] = useState<string>();
const pageDimensions = useWindowDimensions();
const webViewRef = useRef<WebView | null>(null);
const [add, setAdd, swch] = useContext(Context);
useEffect(() => {
if (assets) {
fetch(assets[0].localUri || "")
.then((res) => res.text())
.then((html) => setHtmlString(html));
}
}, [assets]);
useEffect(() => {
if (webViewRef.current) {
console.log(swch)
const functionToCall = swch ? "showMiddlemarker();" : "hideMiddlemarker();";
webViewRef.current.injectJavaScript(`${functionToCall}; true;`);
}
}, [swch]);
if (!htmlString) {
return null;
}
return (
<WebView
ref={(r) => (webViewRef.current = r)}
javaScriptEnabled
source={{
html: htmlString,
}}
style={{
width: pageDimensions.width,
height: pageDimensions.height,
}}
scrollEnabled={false}
overScrollMode="never"
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
scalesPageToFit={false}
containerStyle={{ flex: 1 }}
onLoad={() => {
webViewRef.current?.injectJavaScript(`
function showMiddlemarker() {
console.log("Showing marker");
markerElement.style.display = "block";
}
function hideMiddlemarker() {
console.log("Hiding marker");
markerElement.style.display = "none";
}
true;
`);
}}
/>
);
};
export default Page;
This is the component that loads the built HTML with the map. As you can see, I have tried loading the functions inside onLoad(). The swch variable should control the behavior of the marker. I've checked it's state and it changes when i press the button from true to false correctly.
import "./style.css"
import Feature from 'ol/Feature.js';
import Map from 'ol/Map.js';
import Overlay from 'ol/Overlay.js';
import Point from 'ol/geom/Point.js';
import View from 'ol/View.js';
import {Icon, Style} from 'ol/style.js';
import {OGCMapTile, OSM, Vector as VectorSource} from 'ol/source.js';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer.js';
import { fromLonLat } from 'ol/proj';
const coords = fromLonLat([25.91667,47.85])
const map = new Map({
target: 'map',
layers: [
new TileLayer({
source: new OSM(),
}),
],
view: new View({
center: coords,
zoom: 13,
}),
});
const marker = new VectorLayer({
source: new VectorSource({
features:[
new Feature({
geometry: new Point(
coords
)
})
]
}),
style: new Style({
image: new Icon({
src:"https://i.imgur/oOGwJW8.png",
scale:0.07
})
})
})
const markerElement = document.createElement("div");
markerElement.className = "marker";
markerElement.style.width = "32px";
markerElement.style.height = "32px";
markerElement.style.backgroundImage = "url('https://i.imgur/oOGwJW8.png')";
markerElement.style.backgroundSize = "contain";
markerElement.style.position = "absolute";
markerElement.style.transform = "translate(-50%, -50%)";
markerElement.style.display = "block"
const markerOverlay = new Overlay({
element: markerElement,
positioning: "center-center",
stopEvent: false,
});
map.addOverlay(markerOverlay);
map.getView().on("change:center", () => {
const center = map.getView().getCenter();
markerOverlay.setPosition(center);
});
markerOverlay.setPosition(coords);
//map.addLayer(marker)
function hideMiddlemarker() {
markerElement.style.display = "none";
}
function showMiddlemarker() {
markerElement.style.display = "block";
}
Here is the JS project with the map. I'm trying to call showMiddlemarker and hideMiddlemarker inside the react native app but it won't work at all. I've also checked if the webview is loading beforehand. Tried the onMessage method and it works, but the injectJavascript wont run those 2 functions.
Share Improve this question asked yesterday Tecleanu IonutTecleanu Ionut 371 silver badge6 bronze badges1 Answer
Reset to default 0The problem you're facing is that the injectJavaScript method in your React Native WebView isn't executing the showMiddlemarker and hideMiddlemarker functions as expected. This is a common issue when working with WebView and JavaScript injection, and it usually boils down to timing, scope, or communication issues between React Native and the WebView.
- Use onMessage to debug and confirm the functions are being called.
- Use onLoadEnd instead of onLoad to ensure the WebView is fully loaded.
- Try adding more logs to where is the issue exactly share logs here