react-native-webview-messaging
react-native-webview-messaging copied to clipboard
Setting onMessage on a WebView overrides existing values of window.postMessage
I've got this error on iOS when running the project, working well on Android
I tried adding this to my WebView it removed the error, but the events were not being called after
injectedJavaScript="window.postMessage = String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage');"
Bug reference: https://github.com/facebook/react-native/issues/10865
@SamBellerose Could you please provide code sample you're getting this error with?
Hi,
I'm experiencing a similar issue. Did anyone find a solution?
Moses
@SamBellerose, @mosesmc52 could you please provide more details? I will be really great to assist you
@R1ZZU, user @PaddyLock is using my react-native-webview-braintree package and has run into the same error on iOS (no problems in in Android). I'm sure it's the same problem that @SamBellerose and @mosesmc52 .
It also looks like the issue is being referenced in the react-native issue thread here https://github.com/facebook/react-native/issues/10865.
Here is the code from my package that experiences the issue.
export default class BraintreePaymentWebview extends React.Component {
constructor() {
super();
this.state = {
paymentAPIResponse: null,
showGetNonceActivityIndicator: false,
showSubmitPaymentActivityIndicator: false
};
}
componentDidMount() {
// register listeners to listen for events from the html
// we'll receive a nonce once the requestPaymentMethodComplete is completed
this.registerMessageListeners();
console.log('wbvw braintree mounted');
}
registerMessageListeners = () => {
const { messagesChannel } = this.webview;
messagesChannel.on('RETRIEVE_NONCE_PENDING', event => {
this.setState({ showGetNonceActivityIndicator: true });
console.log('RETRIEVE_NONCE_PENDING');
});
messagesChannel.on('RETRIEVE_NONCE_FULFILLED', event => {
console.log('RETRIEVE_NONCE_FULFILLED');
this.setState({ showGetNonceActivityIndicator: false });
this.setState({ showSubmitPaymentActivityIndicator: true });
this.props.nonceObtainedCallback(event.payload.response.nonce);
});
messagesChannel.on('RETRIEVE_NONCE_REJECTED', event => {
console.log('RETRIEVE_NONCE_REJECTED');
this.setState({ showGetNonceActivityIndicator: false });
});
messagesChannel.on('GO_BACK', () => {
this.props.navigationBackCallback();
});
};
// send the client token to HTML file to begin the braintree flow
// called when the HTML in the webview is loaded
sendClientTokenToHTML = () => {
this.webview.emit('TOKEN_RECEIVED', {
payload: {
clientToken: this.props.clientToken,
options: this.props.options
}
});
};
// handle purchase responses that parent component sends after making purchase API call
handlePurchaseResponse = response => {
console.log('handlePurchaseResponse');
if (response === 'PAYMENT_SUCCESS') {
console.log('emitting purchaseSuccess');
this.setState({ showSubmitPaymentActivityIndicator: false });
this.webview.emit('PURCHASE_FULFILLED');
} else {
this.setState({ showSubmitPaymentActivityIndicator: false });
this.webview.emit('PURCHASE_REJECTED');
}
};
componentWillReceiveProps = nextProps => {
console.log({ nextProps });
if (nextProps.paymentAPIResponse !== this.state.paymentAPIResponse) {
console.log(nextProps.paymentAPIResponse);
this.setState({ paymentAPIResponse: nextProps.paymentAPIResponse });
this.handlePurchaseResponse(nextProps.paymentAPIResponse);
}
};
render() {
return (
<View
style={{
flex: 1,
backgroundColor: 'green'
}}
>
<View
style={{
flex: 1,
backgroundColor: 'blue'
}}
>
<WebView
onLoad={this.sendClientTokenToHTML}
source={require('./dist/index.html')}
style={{ flex: 1 }}
ref={component => (this.webview = component)}
/>
</View>
{renderIf(this.state.showGetNonceActivityIndicator)(
<View style={styles.activityOverlayStyle}>
<View style={styles.activityIndicatorContainer}>
<ActivityIndicator
size="large"
animating={this.state.showGetNonceActivityIndicator}
color="blue"
/>
</View>
</View>
)}
{renderIf(this.state.showSubmitPaymentActivityIndicator)(
<View style={styles.activityOverlayStyle}>
<View style={styles.activityIndicatorContainer}>
<ActivityIndicator
size="large"
animating={this.state.showSubmitPaymentActivityIndicator}
color="green"
/>
</View>
</View>
)}
</View>
);
}
}
BraintreePaymentWebview.propTypes = {
options: PropTypes.object,
clientToken: PropTypes.string.isRequired,
paymentAPIResponse: PropTypes.string.isRequired,
nonceObtainedCallback: PropTypes.func.isRequired,
navigationBackCallback: PropTypes.func
};
I'll try to do some more investigating to figure out what specific portion of my code initiates the problem.
@reggie3 I will investigate this issue and try to provide appropriate workaround
Thanks. Let me know if I can help.
Also running into this issue - very interested in a resolution.
Same issue
I did a PR for this in #22 , it solved it for me, and it relies on a fix suggested in https://github.com/facebook/react-native/issues/10865. I don't know if this breaks other stuff though. @R1ZZU @reggie3 @Maximell @lBroth can you test to check if it works for you as well and it is not breaking anything?