How to integrate the Twitter widget into Reactjs? - twitter

I want to add the Twitter widget into React, but I don't know where to start or how to do it. I am very new to React JS.
Here is the HTML version of the code:
<div class="Twitter">
<a class="twitter-timeline" href="https://twitter.com/<%= #artist.twitter %>" data-widget-id="424584924285239296" data-screen-name='<%= #artist.twitter %>'>Tweets by #<%= #artist.twitter %></a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
</div>
And here is what I have so far:
React.DOM.div
className: 'Twitter'
children: [
React.DOM.a
className: 'twitter-timeline'
href: "https://twitter.com/" + artist.twitter
'data-widget-id': "424584924285239296"
'data-screen-name': artist.twitter
children: 'Tweets by ' + artist.twitter
React.DOM.script
children: ...
]
I was planning to add the script where the dots (...) are, but that doesn't work. Thank you for your help.

First load Widget JS in your index.html(before your React scripts). Then in your component, simply do the following. The widget JS will rescan the DOM.
componentDidMount: function() {
twttr.widgets.load()
}
See: https://dev.twitter.com/web/javascript/initialization

This works for me!
Please note that I use React v0.14 and ECMAScript 2015 (aka ES6) with Babel.
index.html (after body tag):
<script>window.twttr = (function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0], t = window.twttr || {};
if (d.getElementById(id)) return t;
js = d.createElement(s); js.id = id;
js.src = "https://platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
t._e = []; t.ready = function(f) {
t._e.push(f);
};
return t;
}(document, "script", "twitter-wjs"));
</script>
Twitter component:
const Twitter = () => (
<a href="https://twitter.com/your-twitter-page"
className="twitter-follow-button"
data-show-count="false"
data-show-screen-name="false"
>
</a>
);
Some React Component (that uses Twitter button):
class SomeReactComponent extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<Twitter />
</div>
);
}
}
Or if you want to have a customized button, you can simply do this:
const Twitter = () => (
<a href="https://twitter.com/intent/tweet?via=twitterdev">
<i className="zmdi zmdi-twitter zmdi-hc-2x"></i>
</a>
);

It seems to be much easier to just use Twitter's widgets.js, more specifically createTimeline.
class TwitterTimeline extends Component {
componentDidMount() {
twttr.ready(() => {
twttr.widgets.createTimeline(widgetId, this.refs.container)
})
}
render() {
return <div ref="container" />
}
}
You can load the library directly from https://platform.twitter.com/widgets.js, but they recommend the following snippet:
<script>window.twttr = (function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0],
t = window.twttr || {};
if (d.getElementById(id)) return t;
js = d.createElement(s);
js.id = id;
js.src = "https://platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
t._e = [];
t.ready = function(f) {
t._e.push(f);
};
return t;
}(document, "script", "twitter-wjs"));</script>
More information on setting up the library is here.

It's easy, all you need just use React's componentDidMount hook
{createClass, DOM:{a}} = require "react"
#TwitterWidget = createClass
componentDidMount: ->
link = do #refs.link.getDOMNode
unless #initialized
#initialized = yes
js = document.createElement "script"
js.id = "twitter-wjs"
js.src = "//platform.twitter.com/widgets.js"
link.parentNode.appendChild js
render: ->
{title, content, widget} = #props
a
ref: "link"
className: "twitter-timeline"
href: "https://twitter.com/#{widget.path}"
"data-widget-id": widget.id,
widget.title
TwitterWidget
widget:
id: "your-widget-id"
title: "Your Twitts"
path: "widget/path"

Try to install the react-twitter-embed by doing npm install react-twitter-embed. Once installed, the usage is pretty simple. Take a look at the screenshot below.
Code Sample:
import React from 'react';
import { TwitterTimelineEmbed } from 'react-twitter-embed';
const TwitterTimeLine = () => {
return (
<TwitterTimelineEmbed
sourceType="profile"
screenName="accimeesterlin" // change to your username
options={{height: 1200}}
/>
);
}
export default TwitterTimeLine;
They also have a list of other components that you can use as well.
List of available components
TwitterShareButton
TwitterFollowButton
TwitterHashtagButton
TwitterMentionButton
TwitterTweetEmbed
TwitterMomentShare
TwitterDMButton
TwitterVideoEmbed
TwitterOnAirButton
Here is a link to the npm package https://www.npmjs.com/package/react-twitter-embed

IMHO you should split it down in two.
A part of your code could be somehow rendered in a React component
/**
* #jsx React.DOM
*/
var React = require('react');
var twitterWidget = React.createClass({
render: function () {
return (
<div class="Twitter">
<a class="twitter-timeline"
href={this.props.link}
data-widget-id={this.props.widgetId}
data-screen-name={this.props.screenName} >
Tweets by {this.props.screenName}
</a>
</div>
);
}
});
React.renderComponent(<twitterWidget link="..." widgetId="..." />, document.getElementById('containerId');
Your script tag could be placed, as a separate React component or as normal HTML just above the closing body tag.

class TwitterShareButton extends React.Component {
render() {
return Tweet
}
componentDidMount() {
// scriptタグが埋め込まれた後にTwitterのaタグが置かれても機能が有効にならないので、すでにscriptタグが存在する場合は消す。
var scriptNode = document.getElementById('twitter-wjs')
if (scriptNode) {
scriptNode.parentNode.removeChild(scriptNode)
}
// ボタン機能の初期化(オフィシャルのボタン生成ページで生成されるものと同じもの)
!function(d,s,id){
var js,
fjs=d.getElementsByTagName(s)[0],
p=/^http:/.test(d.location)?'http':'https';
if(!d.getElementById(id)){
js=d.createElement(s);
js.id=id;
js.src=p+'://platform.twitter.com/widgets.js';
fjs.parentNode.insertBefore(js,fjs);
}
}(document, 'script', 'twitter-wjs');
}
http://qiita.com/h_demon/items/95e638666f6bd479b47b

You can use this React Social Embed Component.
Disclaimer: It is a component created by me.
Install by: npm i react-social-embed.
Usage:
import TweetEmbed from 'react-social-embed'
<TweetEmbed id='789107094247051264' />
/>

There are few interesting solutions out there, but all of those are injecting twitters code to website.
What would I suggest is to create another empty html file just for this widget. Eg. /twitter.html, where you can place all dirty JavaScripts and render widget.
Then when you include:
<iframe src="/twitter.html" />
It will work without any issues. Plus, you have separated external scripts - so it's good for security.
Just add some styling to make it look fine:
twitter.html
html,
body {
margin: 0;
padding: 0;
}
React's iframe
iframe {
border: none;
height: ???px;
}

I knows exactly where is the problem, first you need to understand how does react works.
React is frontend framework, works like all DOM is handled by react, if we directly integrate with DOM then sometimes it very difficult to code, cos React is also Updating that DOM.
As per the Twitter documentation, we cannot add twitter.js after init of web page.
https://dev.twitter.com/web/javascript/initialization
so it better to use some package, react-twitter-embed
Simple step
npm install --save react-twitter-embed
import { TwitterTimelineEmbed } from 'react-twitter-embed';
<TwitterTimelineEmbed
sourceType="profile"
userId={"1029587508445630465"}
options={{height: 400}}
/>
You can check other than timeline integration also using package.
https://romik-mk.medium.com/embed-twitter-timeline-widgets-reactjs-a27cafd7cfb6

Related

You have included the Google Maps JavaScript API multiple times on this page

how can I avoid “You have included the Google Maps JavaScript API multiple times on this page. This may cause unexpected errors.” if I am using google-map-react to display the map and react-places-autocomplete in another component to get the address and coordinates ?
//LocationMapPage component that displays the map box and pass the props to it
class LocationMapPage extends Component {
render() {
let {latLng,name,address} = this.props.location;
return (
<MapBox lat={latLng.lat} lng={latLng.lng} name={name} address={address}/>
)
}
}
//MapBox component
import React from "react";
import GoogleMapReact from 'google-map-react';
import apiKey from "../../configureMap";
const Marker = () => <i className="fa fa-map-marker fa-2x text-danger" />
const MapBox = ({lat,lng, name, address}) => {
const center = [lat,lng];
const zoom = 14;
return (
<div style={{ height: '300px', width: '100%' }}>
<GoogleMapReact
bootstrapURLKeys={{ key: apiKey }}
defaultCenter={center}
defaultZoom={zoom}
>
<Marker
lat={lat}
lng={lng}
text={`${name}, ${address}`}
/>
</GoogleMapReact>
</div>
);
}
export default MapBox;
Map is blank:
The Error in the console:You have included the Google Maps JavaScript API multiple times on this page. This may cause unexpected errors.
How to solve?
I am using google-map-react, react-places-autocomplete in the project.
AS temporary solution to my specific use case where I use the google map API's in two different components I have just added the script in the index.html:
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places"></script>
I did it in order to avoid that particular error as per of the documentation on the react-places-autocomplete GitHub page.
Unfortunately the link in the head of the index.html caused the same error. I found another workaround. Not the best solution, but works for now:
import React, { useEffect, useState } from 'react';
import GoogleMapReact from 'google-map-react';
export default () => {
const [mapActive, setMapActive] = useState(false);
useEffect(() => {
const t = setTimeout(() => {
setMapActive(true)
}, 100);
return () => {
window.clearTimeout(t);
};
}, [])
return (
<>
{ mapActive && <GoogleMapReact
bootstrapURLKeys={ {
key: ...,
language: ...
} }
defaultCenter={ ... }
defaultZoom={ ... }
>
</GoogleMapReact> }
</>
);
};
You could set a global variable and load the Google JavaScript only if the global variable is not set:
<script type="text/javascript">
if(document.isLoadingGoogleMapsApi===undefined) {
document.isLoadingGoogleMapsApi=true;
var script = document.createElement('script');
script.src='https://maps.googleapis.com/maps/api/js?key=[your-key]&callback=[yourInitMethodName]&v=weekly';
script.type='text/javascript';
script.defer=true;
document.getElementsByTagName('head')[0].appendChild(script);
}else{
[yourInitMethodName]();
}
</script>
In my case there is an arbitrary number of maps in a web application (starting at 0) and the user can add additional maps at runtime.
Most of the users do not use any map so loading it by default would cost unnecessarily loading time.

Ember-cli & Facebook-share buttons - how to?

Goal - Have share buttons for Facebook
I've had various problems, I've managed to solve most issues but never all at the same time.
ReferenceError: FB is not defined (error in the console)
"FB init function gives wrong version error" (error in the console)
My button does not render after transitioned to another route.
My button renders but there is no spacing around the button to adjacent stuff on the initial route
About that rendering issue (the - / hyphen is there to notice the spacing issue)
Rendering for the 1st time:
Rendering for the 2nd+ time:
What I've learned:
Facebook wants a <div id="fb-root"></div> as the first element inside your <body>
FB.XFBML.parse() can be called after didInsertElement to render a component after a transition
I made a JSBin boilerplate attempt, it's currently stuck at a undefined FB error.
http://emberjs.jsbin.com/fevoyuhiso/2/edit
Partial answer I'm also interested in:
Understanding how complex the solution at least must me to achieve a good result ("it must include an initializer, and a view/component!" or "you can solve this by just having ...")
Parts that may be of use
A post about "after FB.init()"
How to detect when facebook's FB.init is complete
An initializer
/* global FB */
export default {
name: 'facebook',
initialize: function() {
var fbAsyncInit = function() {
FB.init({
appId : 123,
xfbml : true,
version : 'v2.2'
});
};
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
window.fbAsyncInit = fbAsyncInit;
}
};
A component
/* global FB */
import Ember from 'ember';
export default Ember.Component.extend({
tagName: 'div',
classNames: 'fb-like',
attributeBindings: [
'data-href',
'data-layout',
'data-action',
'data-show-faces',
'data-share'
],
onDidInsertElement: function() {
Ember.run.schedule('afterRender', FB.XFBML.parse);
}.on('didInsertElement'),
init: function() {
Ember.run.schedule('afterRender', FB.XFBML.parse);
}
});
A script tag
<script type="text/javascript" src="//connect.facebook.net/en_US/sdk.js#xfbml=1&appId=123&version=v2.2"></script>
The root div facebook asks for
<div id="fb-root"></div>
Loading Facebook SDK
import ENV from "my-app/config/environment";
import setupOfflineMode from "my-app/utils/offline-mode";
export function initialize(container, application) {
// offline mode stubs `FB`
if (ENV.offlineMode) { return setupOfflineMode(); }
// Wait for Facebook to load before allowing the application
// to fully boot. This prevents `ReferenceError: FB is not defined`
application.deferReadiness();
var fbAsyncInit = function() {
initFacebook(window.FB);
application.advanceReadiness();
};
loadFacebookSDK();
window.fbAsyncInit = fbAsyncInit;
}
function loadFacebookSDK() {
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
}
function initFacebook(FB) {
FB.init({
appId: ENV.FB_APP_ID,
status: true,
cookie: true,
xfbml: true,
version: ENV.GRAPH_API_VERSION
});
}
export default {
name: 'facebook',
initialize: initialize
};
Share Links
I think this is all I needed to do; I hope I'm not forgetting something...
I didn't set up a component, so this is just a regular view, but it should work about the same.
<div class="fb-share-button" {{bind-attr data-href=link}} data-type="button"></div>
export default Ember.View.extend({
setupSocialNetworks: function() {
Ember.run.scheduleOnce('afterRender', this, function() {
FB.XFBML.parse();
});
}.on('didInsertElement')
});
UPDATE: Alternate solutions
I think which solution you use really depends on your needs. I'm focusing on a faster time-to-first-render, so I've changed my project to not deferReadiness for the Facebook SDK.
I've been playing with two solutions, again I think it totally depends on your needs.
Load the Facebook SDK in an initializer, but set a global promise for access.
This starts the loading on boot, but allows your application to continue booting without having to wait for Facebook. All calls to the Facebook API need to be accessed through the promise.
I'll share the details of this one if requested, but for now I'll just focus on the next solution:
Load the Facebook SDK only on demand in a service.
As before, all access to the Facebook API will need to go through a promise, but this time it is nicely encapsulated in a service and is only loaded on demand:
// app/services/facebook.js
import Ember from 'ember';
import ENV from "juniper/config/environment";
var computed = Ember.computed;
var RSVP = Ember.RSVP;
var _facebookSDKDeferrable = Ember.RSVP.defer();
var fbAsyncInit = function() {
_initFacebook(window.FB);
_facebookSDKDeferrable.resolve(window.FB);
};
window.fbAsyncInit = fbAsyncInit;
export default Ember.Service.extend({
// Resolves when the Facebook SDK is ready.
//
// Usage:
//
// facebook: Ember.inject.service(),
// foo: function() {
// this.get('facebook.SDK').then(function(FB) {
// // Facebook SDK is ready and FB is a reference to the SDK
// });
// }
SDK: computed.alias('FB'),
FB: computed(function() {
_loadFacebookSDK();
return _facebookSDKDeferrable.promise;
})
// I've also put promisified helpers for Facebook SDK
// methods here.
});
function _loadFacebookSDK() {
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
}
function _initFacebook(FB) {
FB.init({
appId: ENV.FB_APP_ID,
status: true,
cookie: true,
xfbml: false,
version: ENV.GRAPH_API_VERSION
});
}
Note also that I've set xfbml to false in FB.init. If your share links have been rendered before the SDK gets loaded, FB.init({ xfbml: true }) will "parse" them, and your FB.XFBML.parse() call will do it again. By setting xfbml to false, you ensure that FB.XFBML.parse() will only get called once.

Twitter bind event after tweet ( twttr.events.bind ) Not Working

I have this simple code That is suppose to alert "I just Tweeted", does not seem to work, i have tried all examples. Even visited this link for help https://dev.twitter.com/discussions/671 but still never worked.
<script>
function alertAfterTweet() {
alert('I just Tweeted')
}
//Bind the custom function with twitter event
twttr.ready(function (twttr) {
twttr.events.bind('click', alertAfterTweet);
});
function jsTweet() {
var urlTW = "https://twitter.com/intent/tweet?text=Text&url=http://example.com";
window.open(urlTW, "", "toolbar=0, status=0, width=650, height=360");
}</script>
Tweet
</script>
Please any help will be appreciated. Thanks
1.First include twitter api
<script>window.twttr = (function (d, s, id) {
var t, js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src= "https://platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
return window.twttr || (t = { _e: [], ready: function (f) { t._e.push(f) } });
}(document, "script", "twitter-wjs"));</script>
2.Create the share button using the twitter API and then bind the event (it looks like you want to bind tweet not click):
twttr.ready(function(twttr) {
twttr.widgets.createShareButton(
'your url',
document.getElementById('your-element-id'), {
url: 'your url',
count: 'none',
text: 'your text',
size: 'large',
hashtags: 'your hashtag'
}).then(function(el) {
console.log("Twitter Button created.")
});
twttr.events.bind('tweet', function(event) {
//add ur post tweet stuff here
console.log('tweet');
});
});
There are many options you can set using the API. for more info:
Javascript: https://dev.twitter.com/web/javascript
Events: https://dev.twitter.com/web/javascript/events
By the way, you can also create the button this way:
<a class="twitter-share-button" href="https://twitter.com/share"
data-related="twitterdev"
data-size="large"
data-count="none">
Tweet
</a>
Hope that helps!

Twitter timeline widget resets iframe content after jquery-ui toggle effect

After googling and analyzing DOM, i found out:
iframe dynamically replaces twitter's timeline a-link
jquery-ui effects force iframe to reload content
similar question
sample at jsfiddle
html
click here to start toggle
<div id="panel">
<a id="twitter-widget" class="twitter-timeline" href="https://twitter.com/search? q=%23Globallogic" data-widget-id="418408420543184896">#Globallogic</a>
</div>
css
#panel {
background:gray;
width:640px;
height:512px;
}
js
!function(d,s,id){var js,fjs=d.getElementsByTagName(s) [0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
$( window ).mousedown(function() {
$( "#panel" ).toggle( "slide", { direction: "left" }, 1000 );
});
Is it possible to configure jquery-ui to avoid iframe reload? and I'm appreciated for any other suggestions.
You can use the following code to reload the twitter widget's content:
twttr.widgets.load()
Be sure to run it after the widget has initially loaded as it will throw up an error otherwise.
I just encountered this issue and I resolved it by dynamically loading child elements to the panel
and ask twitter to load the widget. To do this , if below is you twitter div
then
<div id="panel">
<a id="twitter-widget" class="twitter-timeline" href="https://twitter.com/search?q=%23Globallogic"
data-widget-id="418408420543184896">#Globallogic</a>
</div>
Please place the below java script anywhere using the script tags.
window.twttr = (function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0],
t = window.twttr || {};
if (d.getElementById(id)) return t;
js = d.createElement(s);
js.id = id;
js.src = "https://platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
t._e = [];
t.ready = function (f) {
t._e.push(f);
};return t;
}(document, "script", "twitter-wjs"));
Use setInterval() call the update function. In this function you can remove the existing twitter iframe ( created at the time of loading) , and replace it with your original link. after this is done simply call twttr.widgets.load() a standard event given by twitter
$(function(){
function updateStatus(){
var $twitter = $("#panel");
$twitter.append(" <a id='twitter-widget'
class='twitter-timeline' href='https://twitter.com/search?
q=%23Globallogic' data-widget- id='418408420543184896'>#Globallogic</a>");
twttr.widgets.load();
};
setInterval(function(){updateStatus()}, 1000);
});
Tweets that have images may take some time to load.

twitter widget only load first time in webapp ajax page?

Im trying to load the twitter widget api in my ajax loaded page.
I have tryed to load the script in a couple of different ways and Im getting the alert to run each time but not the script itself.
So the first time I load the page, then the script is working, but if I go back to the menu and back to this page, then it doesnt load it?
This is the ajax loaded page.
<div id="twitterwid">
<a class="twitter-timeline" width="320" height="500" href="https://twitter.com/my account" data-widget-id="my widget id number">Loading tweets by #me</a>
<script>
alert("alert is working");
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
</script>
<div>
Any input appreciated, thanks.
All you have to do is: invoke a re-render of the widget tags on the page by calling:
twttr.widgets.load()
Similar question on Twitter Dev Channel
Note: inline script is not executed upon AJAX Load.
See: this SO Q&A for the solution to that.
Add first :
<script>window.twttr = (function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0],
t = window.twttr || {};
if (d.getElementById(id)) return t;
js = d.createElement(s);
js.id = id;
js.src = "https://platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
t._e = [];
t.ready = function(f) {
t._e.push(f);
};
return t;
}(document, "script", "twitter-wjs"));</script>
So you can use :
twttr.widgets.load()

Resources