I'm trying to load a Twitter widget inside a WebView
in my React Native app, but it seems that my injected Javascript is not working for some reason.
What I'm doing is loading Twitter script asynchronously (function taken from here), then executing twttr.widgets.load()
function when script is loaded in order to draw the widget.
Is it possible to do it, or am I trying an impossible with default Webview
component?
Here is my code:
render() {
let utils = ' \
function loadScript(src, callback) { \
var s, r, t; \
r = false; \
s = document.createElement("script"); \
s.type = "text/javascript"; \
s.src = src; \
s.onload = s.onreadystatechange = function() { \
if ( !r && (!this.readyState || this.readyState == "complete") ) { \
r = true; \
callback(); \
} \
}; \
t = document.getElementsByTagName("script")[0]; \
t.parentNode.insertBefore(s, t); \
} \
';
let twitter = ' \
loadScript("//platform.twitter.com/widgets.js", function () { \
twttr.widgets.load(); \
}); \
';
let JS = utils + twitter;
let source = '<blockquote class="twitter-tweet" data-lang="es"><p lang="en" dir="ltr">8 TED Talks to inspire projects with kids: <a href="https://twitter.com/TEDTalks/status/758116657638309896">https://twitter.com/TEDTalks/status/758116657638309896</a> <a href="https://twitter.com/TEDTalks/status/758116657638309896">pic.twitter.com/HMmYAeP7Km</a></p>— TED Talks (@TEDTalks) <a href="https://twitter.com/TEDTalks/status/758116657638309896">27 de julio de 2016</a></blockquote>';
return (
<WebView
source={{html: source}}
javaScriptEnabled={true}
injectedJavascript={ JS }
/>
);
}
It seems like loading scripts inside a WebView is not working (I don't know why). So to make it work, I need to load Twitter's script using script tag and concatenating it to my HTML code.
render() {
let JS = '<script type="text/javascript" src="https://platform.twitter.com/widgets.js"></script>';
let source = JS + '<blockquote class="twitter-tweet" data-lang="es"><p lang="en" dir="ltr">8 TED Talks to inspire projects with kids: <a href="https://twitter.com/TEDTalks/status/758116657638309896">https://twitter.com/TEDTalks/status/758116657638309896</a> <a href="https://twitter.com/TEDTalks/status/758116657638309896">pic.twitter.com/HMmYAeP7Km</a></p>— TED Talks (@TEDTalks) <a href="https://twitter.com/TEDTalks/status/758116657638309896">27 de julio de 2016</a></blockquote>';
return (
<WebView
source={{html: source}}
javaScriptEnabled={true}
/>
);
}
I hacked it together like this and it mostly works, although height isn't variable which isn't ideal:
import React from "react"
import ReactNative from "react-native"
const { View, WebView, StyleSheet, ActivityIndicator } = ReactNative
export default class EmbeddedTweet extends React.Component {
constructor(props) {
super(props)
this.state = {
loading: true,
embedHtml: null,
}
}
componentDidMount() {
this.setupEmbed()
}
setupEmbed() {
let tweetUrl =
"https://publish.twitter.com/oembed?url=" + encodeURIComponent(this.props.url)
fetch(tweetUrl, { method: "GET", headers: { Accepts: "application/json" } }).then(
resp => {
resp.json().then(json => {
let html = json.html
this.setState({
loading: false,
embedHtml: html,
})
})
}
)
}
renderLoading() {
if (this.state.loading) {
return (
<View style={styles.loadingWrap}>
<ActivityIndicator />
</View>
)
}
}
renderEmbed() {
if (this.state.embedHtml) {
let html = `<!DOCTYPE html>\
<html>\
<head>\
<meta charset="utf-8">\
<meta name="viewport" content="width=device-width, initial-scale=1.0">\
</head>\
<body>\
${this.state.embedHtml}\
</body>\
</html>`
return (
<View style={styles.webviewWrap}>
<WebView source={{ html: html }} style={styles.webview} />
</View>
)
}
}
render() {
return (
<View
style={[styles.container, { height: this.props.height || 300 }, this.props.style]}
>
{this.renderLoading()}
{this.renderEmbed()}
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
loadingWrap: {
flex: 1,
backgroundColor: "#999",
justifyContent: "center",
alignItems: "center",
},
webviewWrap: {
flex: 1,
borderWidth: 1,
borderRadius: 4,
borderColor: "#999",
},
webview: {
flex: 1,
},
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With