Open christinegaribian opened 4 years ago
Seems like a quick fix, any ideas if someone's on it? :)
This kind of malfeasance breaks copyright, just use createRef() in constructor. Still don't know how to do the github pushes
Did anyone got the solution of this issue.
@mrawal3112
EDIT: TwitterTweetEmbed.js: here is a file essentially copied from this library, except to use this.ref = React.createRef()
, with protection from script mounting before DOM mounting on the node in case either window.twttr or this.tw.current fails mount
(Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'
), I have no idea how when it is in componentDidMount, but with a lot of tweets with videos... I best not guess.
import React, { Component } from "react";
import PropTypes from "prop-types";
import ExecutionEnvironment from "exenv";
import script from "scriptjs";
class Forward extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return <div ref={this.props.fwdtwe} />;
}
}
const Forwardd = React.forwardRef((props, ref) => (
<Forward fwdtwe={ref} {...props} />
));
export default class TwitterTweetEmbed extends Component {
static propTypes = {
/**
* Tweet id that needs to be shown
*/
tweetId: PropTypes.string.isRequired,
/**
* Additional options to pass to twitter widget plugin
*/
options: PropTypes.object,
/**
* Placeholder while tweet is loading
*/
placeholder: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
/**
* Function to execute after load, return html element
*/
onLoad: PropTypes.func
};
constructor(props) {
super(props);
this.state = {
giveup: 0,
isLoading: true
};
this.tw = React.createRef();
this.fwdtwe = React.createRef();
}
renderWidget() {
const { onLoad } = this.props;
if (!window.twttr) {
console.error(
"Failure to load window.twttr in TwitterTweetEmbed, aborting load."
);
return;
}
if (!this.tw.current) {
console.error(
"Failure to load this.tw.current in TwitterTweetEmbed, aborting load.",
this.tw.current
);
return;
}
/*let onClick = "ontouchstart" in window ? "touchstart" : "onclick";
if (!this.tw.current["onClick"]) {
console.error(
"Failure to load this.tw.current[onClick] in TwitterTweetEmbed, aborting load.",
this.tw.current["onClick"]
);
return;
}*/
if (!this.isMountCanceled && this.props.tweetId) {
//this.tw.current.innerHTML = React.createElement("div", { ref: this.twe });
//ReactDOM.render(reactElementUl, document.getElementById('app'));
/*ReactDOM.render(
forwardd(), //React.createElement("div", { ref: this.twe }),
this.tw.current
);*/
this.tw.current.innerHTML = <Forwardd fwdtwe={this.fwdtwe} />;
window.twttr.widgets
.createTweet(
this.props.tweetId,
this.fwdtwe.current,
this.props.options
)
.then((element) => {
this.setState({
isLoading: false,
style: { height: "min-content", ...this.props.style }
});
if (onLoad) {
onLoad(element);
}
})
.catch((err) => {
if (this.state.giveup === 2) return null;
this.setState({ giveup: this.state.giveup + 1 }, () => {
clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.renderWidget();
}, 1000); //in case either window.twttr or this.tw.current fails mount
});
});
}
}
componentDidMount() {
if (ExecutionEnvironment.canUseDOM) {
//let script = require("scriptjs");
script("https://platform.twitter.com/widgets.js", "twitter-embed", () => {
this.renderWidget();
});
}
}
componentWillUnmount() {
clearTimeout(this.timer);
this.isMountCanceled = true;
}
render() {
return <div ref={this.tw} style={this.state.style} />;
}
}
TwitterTweetEmbed.js: here is a file essentially copied from this library, except to use this.ref = React.createRef()
import React, { Component } from "react";
import PropTypes from "prop-types";
import ExecutionEnvironment from "exenv";
export default class TwitterTweetEmbed extends Component {
static propTypes = {
/**
* Tweet id that needs to be shown
*/
tweetId: PropTypes.string.isRequired,
/**
* Additional options to pass to twitter widget plugin
*/
options: PropTypes.object,
/**
* Function to execute after load, return html element
*/
onLoad: PropTypes.func
};
constructor(props) {
super(props);
this.state = {
isLoading: true
};
this.tw = React.createRef();
}
renderWidget() {
const { onLoad } = this.props;
if (!window.twttr) {
console.error(
"Failure to load window.twttr in TwitterTweetEmbed, aborting load."
);
return;
}
if (!this.isMountCanceled) {
window.twttr.widgets
.createTweet(this.props.tweetId, this.tw.current, this.props.options)
.then((element) => {
this.setState({
isLoading: false
});
if (onLoad) {
onLoad(element);
}
});
}
}
componentDidMount() {
if (ExecutionEnvironment.canUseDOM) {
let script = require("scriptjs");
script("https://platform.twitter.com/widgets.js", "twitter-embed", () => {
this.renderWidget();
});
}
}
componentWillUnmount() {
this.isMountCanceled = true;
}
render() {
return (
<div ref={this.tw} />
);
}
}
with widget declarations for how to read tweetId
, for isHashtag ("createHashtagButton"
) or isProfile ("createFollowButton"
), lest is "createTweet"
renderWidget() {
const { onLoad } = this.props;
if (!window.twttr) {
console.error(
"Failure to load window.twttr in TwitterTweetEmbed, aborting load."
);
return;
}
if (!this.isMountCanceled) {
let options = Object.assign({}, this.props.options);
var widget = null;
var input = null;
if (this.props.isHashtag) {
widget = "createHashtagButton";
input = this.props.tweetId;
} else if (this.props.isProfile) {
//console.log("twitter profile " + this.props.tweetId);
options = Object.assign({}, options, {
theme: this.props.theme,
linkColor: this.props.linkColor,
borderColor: this.props.borderColor,
lang: this.props.lang
});
widget = "createFollowButton";
input = this.props.tweetId;
/*widget = "createTimeline";
input = {
sourceType: "profile",
screenName: this.props.tweetId,
userId: this.props.userId,
ownerScreenName: this.props.ownerScreenName,
slug: this.props.slug,
id: this.props.id || this.props.widgetId,
url: this.props.url
};*/
} else {
widget = "createTweet";
input = this.props.tweetId;
}
//this.refs.embedContainer
window.twttr.widgets[widget](input, this.tw.current, options).then(
(element) => {
this.setState({
isLoading: false
});
if (onLoad) {
onLoad(element);
}
}
);
}
}
Works great for React 17, but in 18 the tweet just never loads. Is that an easy adjustment as well? No errors so it seems like the tweet component just isn't being attached to the empty placeholder div
in the DOM at all.
When using
TwitterTweetEmbed
inReact.StrictMode
, I get this error in the console: