Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

window.ReactNativeWebView is undefined on Android platform, iOS works just fine. #1829

Closed
Scarle-t opened this issue Jan 18, 2021 · 18 comments
Closed

Comments

@Scarle-t
Copy link

Bug description:

window.ReactNativeWebView is undefined on Android platform, iOS works just fine.

To Reproduce:

Build for both platforms from same project, open Chrome's DevTool and Safari's Web Inspector, type window.ReactNativeWebView in the Console section and send it.

Expected behavior:

Webpage JS can call window.ReactNativeWebView.postMessage() on both platform successfully.
Further action handled within React Native.

Screenshots/Videos:

Console at the top showing iOS console, bottom is Android console
Image showing iOS console at the top, android console at the bottom

Environment:

  • OS: iOS

  • OS version: 14.3

  • react-native version: 0.63.4

  • react-native-webview version: 11.0.2

  • OS: Android

  • OS version: 11

  • react-native version: 0.63.4

  • react-native-webview version: 11.0.2

@fpena
Copy link

fpena commented Jan 21, 2021

I created an example repo where this can be reproduced.

In iOS, an alert shows up because the website is call callback function.
In Android doesn't happen.

Also, the codesandbox with the web-view behaviour.

cc: @jamonholmgren

@joe06102
Copy link

I met the same issue, did you have any good solution?

@Scarle-t
Copy link
Author

Scarle-t commented Jan 22, 2021

Thank you @fpena for providing the sample.
Sorry for not including a sample repo in the first place.

I have been scratching my head for days but no clue until I discovered another issue which cause this to happen.

Apparently the onNavigationStateChange prop returns different naveState.url values on iOS and Android.
I've been rely on this to trigger ReactNavigation's navigation.navigate() to another WebView Stack.
Here's the code:

<WebView
     useWebKit={true}
     allowsInlineMediaPlayback={true}
     javaScriptEnabledAndroid={true}
     javaScriptEnabled={true}
     originWhitelist={['*']}
     source={{ uri: fullLink }}
     bounces={ false }
     pagingEnabled= { true }
     domStorageEnabled={ true }
     style={{marginTop: notch_margin}}
     injectedJavaScriptBeforeContentLoaded={injectBeforeLoad}
     onNavigationStateChange={(event)=>{
       if(event.url.includes('foobar')){
         navigation.navigate(someOtherScreen);
       }
     }}
     onMessage={(event) => {
       //receive message
     }}
   />

@Scarle-t
Copy link
Author

@joe06102 Somehow my issue "disappeared" once I figure out the prop onNavigationStateChange not behaving as expected. The current workaround is to use other prop as conditions.

@fpena
Copy link

fpena commented Jan 22, 2021

@Scarle-t the repo I created doesn't have onNavigationStateChange. It's the minimal way to reproduce. I think the issue is not related to that method.

@Scarle-t
Copy link
Author

@fpena I do aware that the issue may not related to onNavigationStateChange, I just not sure that if having the prop will affect anything, or if I'm doing it wrongly (I'm new to React Native)

@Titozzz
Copy link
Collaborator

Titozzz commented Jan 24, 2021

I'm going to have a look, thanks for the repro @fpena

@Titozzz
Copy link
Collaborator

Titozzz commented Jan 24, 2021

@fpena I'm not sure I can reproduce with your example.

When I inspect the page I can see in the console that window.onload has failed due to callback being undefind, however window.ReactNativeWebView is defined.

To fix and display the alert I just changed your injected JS to window.callback = function() {} and your onload to call the function on the window.

EDIT: Oh also your onload is running potentially before the JS was injected. But there are workaround for that. Let me see how I can share that with you

@fpena
Copy link

fpena commented Jan 24, 2021

@Titozzz Thanks. Looking forward to it.
I added two new example videos to the repo.

@react-native-webview react-native-webview deleted a comment from fpena Jan 25, 2021
@github-actions
Copy link

Hello 👋, this issue has been opened for more than 2 months with no activity on it. If the issue is still here, please keep in mind that we need community support and help to fix it! Just comment something like still searching for solutions and if you found one, please open a pull request! You have 7 days until this gets closed automatically

@github-actions github-actions bot added the Stale label Mar 27, 2021
@JmStefanAndroid
Copy link

same issue

@github-actions github-actions bot removed the Stale label Mar 31, 2021
@github-actions
Copy link

Hello 👋, this issue has been opened for more than 2 months with no activity on it. If the issue is still here, please keep in mind that we need community support and help to fix it! Just comment something like still searching for solutions and if you found one, please open a pull request! You have 7 days until this gets closed automatically

@belyylis
Copy link

belyylis commented Nov 8, 2021

Meeting the same problem. Is there a working solution?

@jswangtao
Copy link

window.ReactNativeWebView.postMessage(JSON.stringify(data));
"react-native": "0.63.3",
"react-native-webview": "11.15.0",

is work for me
image

@linonetwo
Copy link

linonetwo commented Aug 30, 2023

I encounter this today, luckily I remember I can use it yesterday morning, so I did a git bysect, and found I have this, if I comment the replace out, window.ReactNativeWebView works again (not undefined):

- const modifiedContent = content.replace('</body>', '<script>console.log("loaded")</script></body>');
+ const modifiedContent = content //.replace('</body>', '<script>console.log("loaded")</script></body>');

this modifiedContent is assigned to the ...

wait, I'm using source={{ uri: 'http://192.168.3.15:5212/tw-mobile-sync/get-skinny-html' }} instead of source={{ html: modifiedContent }}, why wound this affect it???

And this only happened after rebuild (by pressing r), so this might be some sort of "compiler magic" where a single .replace statement might mess up the compile result...

@linonetwo
Copy link

This doesn't even work after I do some refactor. So I think this bug needs to be reopened.

@linonetwo
Copy link

race condition!

@linonetwo
Copy link

Make sure onMessage is never undefined by doing this:

    <WebView
      originWhitelist={['*']}
      source={{ html: wikiHTMLString }}
      onMessage={onMessageReference.current ?? ((message) => {
        console.log('WebView onMessage (before onMessageReference.current ready)', message);
      })}
      ref={webViewReference}
      injectedJavaScriptBeforeContentLoaded={preloadScript}
      // Open chrome://inspect/#devices to debug the WebView
      webvie

because

You _must_ set `onMessage` or the `window.ReactNativeWebView.postMessage` method will not be injected into the web page.

I don't think this is a good design, because nowadays some callback are provided by async hooks, for example https://github.com/linonetwo/react-native-postmessage-cat 's useRegisterProxy hook use this logic to provide callback only when conditions meets

https://github.com/linonetwo/react-native-postmessage-cat/blob/6883db1a5d282b069baf505afda949351fb79bc4/src/react-native.ts#L43-L45


So what about .replace? It delay the execution, and @Scarle-t 's onNavigationStateChange did the same. And after that, the callback of onMessage is ready or is not ready. Anyway, this is a matter of time, just like some bug disappear after you add a console.log, so this makes me think of race condition.

But this doc is the fact that really make me realize this

You _must_ set `onMessage` or the `window.ReactNativeWebView.postMessage` method will not be injected into the web page.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants