9

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:

4
  • Could you check you can access webViewRef.current out of addListener? Commented Sep 9, 2020 at 13:10
  • It always seems to be undefined it's so confusing. Commented Sep 9, 2020 at 13:12
  • Can you test your code with a setTimeout with a delay of 3000-5000ms? If the ref is still undefined then something is wrong. And also you can create a useEffect within the array you pass the ref. If it's set it will be called automatically Commented Sep 9, 2020 at 13:26
  • There is definitely something weird about the way this is working with the listener - as I can use the ref if it is called directly inside useEffect. In the listener, even with the timeout, it is not working. Commented Sep 9, 2020 at 14:06

2 Answers 2

22

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

Sign up to request clarification or add additional context in comments.

3 Comments

thank you for this, that capital S in JavaScript really is naughty.
Funny enough I just had one of these terrible situations today with a library where the option I needed was lazyLoad not lazyload
thanks a lot man! I literally spent hours trying to solve this smh!
2

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

2 Comments

Thankyou, this makes sense and I've added the listener to onLoadEnd but am still having the same issue, webViewRef is undefined :(
So this is not working unfortunately, and I think it can be narrowed down to the listener, please see the example in Edit 2 of my post

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.