I’m building a React Native app and having trouble with click events in injected JavaScript code. I’m using react-native-webview to load a feedback form. When users submit the form, a “Thank you” message appears and I want the app to automatically navigate back after 3 seconds.
I’m trying to use the injectedJavaScript prop to add custom JavaScript. The timeout function works fine when called directly, but when I try to attach it to a button’s click event using querySelector, nothing happens. Here’s my code:
import React from "react";
import { View, StyleSheet, ActivityIndicator } from "react-native";
import { WebView } from "react-native-webview";
import { useNavigation } from "@react-navigation/native";
const formUrl = "https://example-form.com/";
export default function FeedbackScreen() {
const nav = useNavigation();
const customJS = `
document.querySelector('#main-container').style.marginTop = 25;
document.getElementsByTagName('h2')[0].style.visibility = 'hidden';
document.getElementsByTagName('logo')[0].style.visibility = 'hidden';
${setTimeout(() => { // this part works fine
nav.goBack();
}, 3000)}
document.querySelector('.submit-btn').onclick= ${function handleClick() { // this doesn't work
setTimeout(() => {
nav.goBack();
}, 3000);
}};
`;
return (
<View style={styles.wrapper}>
<WebView
source={{ uri: formUrl }}
startInLoadingState={true}
renderLoading={() => <ActivityIndicator />}
onMessage={() => {}}
injectedJavaScript={customJS}
javaScriptEnabled={true}
/>
</View>
);
}
const styles = StyleSheet.create({
wrapper: {
flex: 1,
justifyContent: "center",
marginTop: 150,
backgroundColor: "#f5f5f5",
padding: 10,
},
});
Why isn’t the onclick event firing? Is there a different way to handle click events in React Native WebView injected JavaScript?
you’re stringifying functions wrong in that template literal. ${function...} doesn’t work - it just becomes [object Object]. plus nav.goBack() won’t exist in the webview anyway. write your functions as plain strings inside customJS and use postMessage to talk back to the React Native side.
You’re mixing JavaScript string interpolation with template literals wrong. When you use ${setTimeout(...)} and ${function handleClick() {...}}, you’re trying to interpolate the execution results instead of the function code as strings.
Hit this exact problem last year building a similar webview integration. Define your functions as proper string literals within the injected JavaScript. Restructure your customJS like this:
I’m using window.ReactNativeWebView.postMessage() instead of directly calling nav.goBack() because the injected JavaScript runs in the webview context and doesn’t have access to your React Native navigation object. You’ll need to handle the message in your onMessage prop to trigger the actual navigation.
Your JavaScript is broken because of bad string concatenation. You’re trying to use React Native functions inside the webview, but they don’t exist there. I hit this exact problem with a customer survey project.
Webviews run their own JavaScript environment and can’t access your React Native navigation directly. You need to stringify functions properly and use the message bridge.
Try this:
const customJS = `
document.querySelector('#main-container').style.marginTop = '25px';
document.getElementsByTagName('h2')[0].style.visibility = 'hidden';
// Wait for DOM to be ready
setTimeout(function() {
var submitButton = document.querySelector('.submit-btn');
if (submitButton) {
submitButton.addEventListener('click', function() {
setTimeout(function() {
window.ReactNativeWebView.postMessage('goBack');
}, 3000);
});
}
}, 1000);
`;
Use addEventListener instead of onclick, and communicate through the message bridge rather than calling React Native functions from inside the webview.