Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native ref.injectJavascript on WebView always undefined

I have a simple functional component with a WebView inside a TabNavigator where I'd like to inject some javascript when the tab is focused like so:

import React, {useRef, useEffect} from 'react';
import {WebView} from 'react-native-webview';

export default (props) => {

  const webViewRef = useRef();

  React.useEffect(() => {
    const unsubscribe = props.navigation.addListener('focus', () => {
      webViewRef.current.injectJavascript('console.log("Hello World")');
    });
    return unsubscribe;
  }, []);

  return (
    <WebView ref={webViewRef} />
  );
}

For some reason, webViewRef is always undefined in the listener.

If I do something like <WebView ref={(r) => console.log(r)} /> I get something like the following:

screenshot

EDIT:

Simply adjusting the provided example -does- work, so I suppose I will have to figure out what is going on in my code:

import React, { useRef } from 'react'
import { View } from 'react-native'
import { WebView } from 'react-native-webview'

export default () => {

  const webViewRef = useRef(null);

  const run = `
    document.body.style.backgroundColor = 'blue';
    true;
  `

  setTimeout(() => {
    webViewRef.current.injectJavaScript(run)
  }, 3000)

  return (
    <View style={{ flex: 1 }}>
      <WebView
        ref={webViewRef}
        source={{
          uri:
            'https://github.com/react-native-community/react-native-webview',
        }}
      />
    </View>
  )
}

EDIT 2: Adjusting the simple example and attempting to use the ref inside the listener does not work:

import React, { useRef } from 'react'
import { View } from 'react-native'
import { WebView } from 'react-native-webview'

export default (props) => {

  const webViewRef = useRef(null);



  const run = `
    document.body.style.backgroundColor = 'blue';
    true;
  `
  const handleLoadEnd = () => {
    props.navigation.addListener('focus', () => {
      webViewRef.current.injectJavascript(run)
    })
  }

  return (
    <View style={{ flex: 1 }}>
      <WebView
        ref={webViewRef}
        source={{
          uri:
            'https://github.com/react-native-community/react-native-webview',
        }}
        onLoadEnd={handleLoadEnd}
      />
    </View>
  )
}

Edit 3: useFocusEffect also has same problem:

  useFocusEffect(
    React.useCallback(() => {
      webViewRef.current.injectJavascript('alert("HI")')
    }, [props.navigation])
  )

Sources:

  • React Navigation: Call a function when focused screen changes
  • React Native WebView: Communicating between JS and Native
like image 317
waffl Avatar asked May 09 '26 20:05

waffl


2 Answers

Oh man, it's really another one of those epic hair pulling days:

  webViewRef.injectJavascript < BAD
  webViewRef.injectJavaScript < GOOD

Somebody please give the last 4 hours of my life back

like image 113
waffl Avatar answered May 11 '26 09:05

waffl


The ref will be set, if the onLoadEnd event has triggered. So you must adjust your code like so:

export default (props) => {

  const webViewRef = useRef();

  const handleLoadEnd = () => {
    props.navigation.addListener('focus', () => {
      webViewRef.current.injectJavascript('console.log("Hello World")');
    });
  }

  return (
    <WebView ref={webViewRef} onLoadEnd={handleLoadEnd}/>
  );
}

I have a working example. See here https://github.com/Tracer1337/MRGVP/blob/master/vertretungsplan/components/PaginatedWebview/PaginatedWebview.js

like image 26
Tracer69 Avatar answered May 11 '26 11:05

Tracer69



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!