[英]React Native WebView JavaScript issue on build
I've got a React Native application for Android that has live chat support (using Intercom). 我有一个具有实时聊天支持(使用内部通信)的Android React Native应用程序。 To access Intercom I'm using
WebView
with injectedJavaScript
to show the UI. 要访问对讲我使用
WebView
与injectedJavaScript
以显示UI。 It works fine on my dev build, but when I do a release build it complains it cannot find window.Intercom
(I get the same relative issue if I remove the window.
) 它在我的开发版本上运行良好,但是当我进行发布版本时,它抱怨找不到
window.Intercom
(如果删除window.
我会遇到相同的相对问题window.
)
Here's the code I'm trying to run 这是我要运行的代码
IntercomContainer.js IntercomContainer.js
// =============================================================================
// Components >> IntercomContainer
// =============================================================================
// @flow
// Import
// =============================================================================
import * as React from 'react';
import { View, WebView } from 'react-native';
import Spinner from 'react-native-loading-spinner-overlay';
import styles from './styles';
// Content
// =============================================================================
type State = {
isLoading: boolean,
};
type Props = {
appId: string,
}
// Render
// =============================================================================
export default class IntercomContainer extends React.Component<Props, State> {
props: Props = {
appId: '',
};
state: State = {
isLoading: true,
}
setState: Function;
injectedJS = (appId: string) => {
return `
try {
window.Intercom('boot', {
app_id: '${appId}',
});
window.Intercom('show');
window.Intercom('onShow', function() {
document.getElementById('message').innerHTML = '';
setTimeout(() => {
document.getElementById('message').innerHTML = 'Click on the chat button in the bottom-right to open chat...';
}, 1000)
});
} catch(e) {
alert('Intercom failed to load: ' + e.message);
}
`;
}
onLoadEnd = () => {
this.setState({
isLoading: false,
});
}
render(){
const { appId } = this.props;
const { isLoading } = this.state;
return (
<View style={styles.container}>
<Spinner visible={isLoading} />
<WebView
injectedJavaScript={this.injectedJS(appId)}
source={require('./IntercomWebView.html')}
onLoadEnd={this.onLoadEnd}
javaScriptEnabled={true}
style={styles.webView}
/>
</View>
);
}
}
IntercomWebView.html IntercomWebView.html
<!DOCTYPE html>
<head>
<script>
// intercom JS library
var APP_ID = '';
(function(){
debugger;
console.log("Executing function main...");
var w=window;
var ic=w.Intercom;
if (typeof ic === "function") {
ic('reattach_activator');
ic('update',intercomSettings);
} else {
var d=document;
var i= function() {
i.c(arguments)
};
i.q=[];
i.c=function(args){
i.q.push(args)
};
w.Intercom=i;
function l(){
debugger;
console.log("Executing function l...");
var s=d.createElement('script');
s.type='text/javascript';
s.async=true;
s.src='https://widget.intercom.io/widget/' + APP_ID;
var x=d.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s,x);
}
if(w.attachEvent){
w.attachEvent('onload',l);
}else{
w.addEventListener('load',l,false);
}
}
})();
</script>
<style>
main {
align-items: center;
background-color: #fefefe;
color: #999;
display: flex;
font-family: sans-serif;
height: 80vh;
justify-content: center;
text-align: center;
}
</style>
</head>
<body>
<main id="message">
loading...
</main>
</body>
</html>
Thanks! 谢谢!
Most likely the root cause of your issue is the same as postMessage bug. 您问题的根本原因很可能与postMessage错误相同。 Your code which uses
Intercom
object is being loaded before javascript code which initilizes this object. 使用
Intercom
对象的代码将在初始化该对象的JavaScript代码之前加载。 As a workaround you can call this code in setTimeout
with some magic value, or implement more "neat" solution where you'll defer actual calls of Intercom
object until it is initialized 作为一种解决方法,您可以使用一些神奇的值在
setTimeout
调用此代码,或者实施更多的“整洁”的解决方案 ,在此解决方案中 ,您将对Intercom
对象的实际调用推迟到初始化之前
This seems to be an issue as referred to above with the delay, but also a cookies
problem. 这似乎是上面提到的延迟问题,但也是
cookies
问题。
I managed to get around this with the following, similar to the original question; 我设法通过以下方法解决了这个问题,类似于原始问题。
const injectedJavaScript = `
var APP_ID = "YOUR_APP_ID";
// Wait for a "time" before trying to execute
setTimeout(function() {
try {
window.Intercom('boot', {
app_id: APP_ID,
email: 'an_email_@an_address.com',
user_id: 'unique_id'
});
// i want to show by default, when ready
window.Intercom('show');
// then i am doing some stuff to show the "instruction" to reopen by the icon if they close
var instruction = document.getElementById("instruction");
window.Intercom('onHide', function() {
instruction.classList.add("show");
})
} catch(e) {
alert('Intercom failed to load: ' + e.message);
}
}, 500)
`
My WebView looks like this; 我的WebView看起来像这样;
return (
<View flex={1}>
<WebView
javaScriptEnabled
scrollEnabled={false}
bounces={false}
originWhitelist={['*']}
injectedJavaScript={injectedJavaScript}
source={{
html: `
<head>
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0">
<style>
p#instruction {
opacity: 0;
font-family: 'Rubik', sans-serif;
text-align: center;
font-size: 14px;
position: absolute;
top: 50%;
left: 0;
margin-top: -8px;
width: 100%;
-webkit-transition: opacity 0.5s linear;
-moz-transition: opacity 0.5s linear;
-o-transition: opacity 0.5s linear;
-ms-transition: opacity 0.5s linear;
transition: opacity 0.5s linear;
}
p#instruction.show {
opacity: 1;
}
</style>
</head>
<body>
<p id="instruction">Click the icon to open chat</p>
<script>
var APP_ID = "YOUR_APP_ID";
(function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',w.intercomSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Intercom=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://widget.intercom.io/widget/' + APP_ID;var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();
</script>
</body>
`,
baseUrl: 'https://a-base-url.co.uk', // This part is important! This solved the cookie issue for me
}}
useWebKit
onLoad={() => console.warn('do something on load')}
/>
</View>
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.