You have included the Google Maps JavaScript API multiple times on this page - google-map-react

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.

Related

How do I use slots with a Quasar Dialog Plugin custom component?

I want to make a custom component for the Quasar Dialog. And inside that component I want to use slots, but I'm not sure how to do that.
This is my CustomDialogComponent.vue where I have defined a cancelBtn slot and a confirmBtn slot:
<template>
<!-- notice dialogRef here -->
<q-dialog ref="dialogRef" #hide="onDialogHide">
<q-card class="q-dialog-plugin">
<q-card-section>
<strong>{{ title }}</strong>
</q-card-section>
<q-card-section>
<slot name="cancelBtn" #click="handleCancelClick"></slot>
<slot name="confirmBtn" #click="handleConfirmClick"></slot>
</q-card-section>
</q-card>
</q-dialog>
</template>
<script setup lang="ts">
import { PropType } from 'vue';
import { useDialogPluginComponent } from 'quasar';
defineProps({
title: {
type: String,
required: false,
default: 'Alert',
},
});
defineEmits([
...useDialogPluginComponent.emits,
]);
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
useDialogPluginComponent();
const handleConfirmClick = () => {
console.log('Confirm Button Clicked');
onDialogOK();
};
const handleCancelClick = () => {
console.log('Cancel Button Clicked');
onDialogCancel();
};
</script>
And the Quasar docs show that I can invoke it via a $q.dialog({ ... }) Object. With props etc all set inside that object. So that would look something like this:
<template>
<div #click="showDialog">Show The Dialog</div>
</template>
<script setup lang="ts">
import { useQuasar } from 'quasar';
import CustomDialogComponent from 'src/components/CustomDialogComponent.vue'
const $q = useQuasar();
const showDialog = () => {
$q.dialog({
component: CustomDialogComponent,
// props forwarded to your custom component
componentProps: {
title: 'Alert title goes here',
},
})
};
</script>
But there are no properties inside the Dialog Object for me to pass in my slots. So where can I pass in the cancelBtn and confirmBtn slots I created in CustomDialogComponent.vue?
I asked directly and apparently there is no way to use slots at this time. They might add this functionality later.

How to keep popup of Quasar Select component open?

I'm working to create a geocoding component that allows a user to search for their address, using Quasar's <q-select /> component. I'm running in to one issue with the popup however.
After a user enter's the search query, I fetch the results from an API and the results are set to a reactive local state (which populates the select's options). Instead of the popup displaying though, it closes, and I have to click on the chevron icon twice for the popup to display the results.
This first image is what it looks like when I first click in to the input.
The second image shows what happens after entering a query. The data is fetched, options are set, and the popup closes.
The third image shows the select after clicking on the chevron icon twice.
How do I programmatically show the popup, so that once the results are fetched, the popup is displayed correctly?
Edit: Created a working repro here.
<template>
<q-select
ref="geolocateRef"
v-model="state.location"
:options="state.locations"
:loading="state.loadingResults"
clear-icon="clear"
dropdown-icon="expand_more"
clearable
outlined
:use-input="!state.location"
dense
label="Location (optional)"
#clear="state.locations = undefined"
#input-value="fetchOptions">
<template #prepend>
<q-icon name="place " />
</template>
<template #no-option>
<q-item>
<q-item-section class="text-grey">
No results
</q-item-section>
</q-item>
</template>
</q-select>
</template>
<script lang='ts' setup>
import { reactive } from 'vue';
import { debounce, QSelect } from 'quasar';
import { fetchGeocodeResults } from '#/services';
const state = reactive({
location: undefined as string | undefined,
locations: undefined,
loadingResults: false,
geolocateRef: null as QSelect | null,
});
const fetchOptions = debounce(async (value: string) => {
if (value) {
state.loadingResults = true;
const results = await fetchGeocodeResults(value);
state.locations = results.items.map(item => ({
label: item.title,
value: JSON.stringify(item.position),
}));
state.loadingResults = false;
state.geolocateRef?.showPopup(); // doesn't work?
}
}, 500);
</script>
I'd also posted this question over in the Quasar Github discussions, and someone posted a brilliant solution.
<template>
<q-select
v-model="state.location"
:use-input="!state.location"
input-debounce="500"
label="Location (optional)"
:options="options"
dense
clear-icon="bi-x"
dropdown-icon="bi-chevron-down"
clearable
outlined
#filter="fetchOptions">
<template #prepend>
<q-icon name="bi-geo-alt" />
</template>
<template #no-option>
<q-item>
<q-item-section class="text-grey">
No results
</q-item-section>
</q-item>
</template>
</q-select>
</template>
<script lang='ts' setup>
import { reactive, ref } from 'vue';
import { QSelect } from 'quasar';
import { fetchGeocodeResults } from '#/services';
interface Result {
position: {
lat: number;
lng: number;
}
title: string;
}
const state = reactive({
...other unrelated state,
location: undefined as string | undefined,
});
const options = ref([]);
const fetchOptions = async (val: string, update) => {
if (val === '') {
update();
return;
}
const needle = val.toLowerCase();
const results = await fetchGeocodeResults(needle);
options.value = results.items.map((item: Result) => ({
label: item.title,
value: JSON.stringify(item.position),
}));
update();
};
</script>

Snazzy Maps in Rails Application

I set up a nice map in my rails application. Everything is working fine but I cannot style the map with SnazzyMaps.
Here is my map.js file:
import GMaps from 'gmaps/gmaps.js';
const mapElement = document.getElementById('map');
if (mapElement) { // don't try to build a map if there's no div#map to inject in
const map = new GMaps({ el: '#map', lat: 0, lng: 0 });
const markers = JSON.parse(mapElement.dataset.markers);
const mapMarkers = map.addMarkers(markers);
mapMarkers.forEach((marker, index) => {
marker.addListener('click', () => {
// map.setCenter(markers[index]);
markers[index].infoWindow.open(map, marker);
})
});
if (markers.length === 0) {
map.setZoom(2);
} else if (markers.length === 1) {
map.setCenter(markers[0].lat, markers[0].lng);
map.setZoom(14);
} else {
map.fitLatLngBounds(markers);
}
}
import { autocomplete } from '../components/autocomplete';
// [...]
autocomplete();
On SnazzyMaps they give the following example. My question is, where shall I insert which part of this code in my own file. Been trying it for a while now but cannot make it work. Here is SnazzyMaps example:
<!DOCTYPE html>
<html>
<head>
<title>Snazzy Maps Super Simple Example</title>
<style type="text/css">
/* Set a size for our map container, the Google Map will take up 100% of this container */
#map {
width: 750px;
height: 500px;
}
</style>
<!--
You need to include this script tag on any page that has a Google Map.
The following script tag will work when opening this example locally on your computer.
But if you use this on a localhost server or a live website you will need to include an API key.
Sign up for one here (it's free for small usage):
https://developers.google.com/maps/documentation/javascript/tutorial#api_key
After you sign up, use the following script tag with YOUR_GOOGLE_API_KEY replaced with your actual key.
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=YOUR_GOOGLE_API_KEY"></script>
-->
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js"></script>
<script type="text/javascript">
// When the window has finished loading create our google map below
google.maps.event.addDomListener(window, 'load', init);
function init() {
// Basic options for a simple Google Map
// For more options see: https://developers.google.com/maps/documentation/javascript/reference#MapOptions
var mapOptions = {
// How zoomed in you want the map to start at (always required)
zoom: 11,
// The latitude and longitude to center the map (always required)
center: new google.maps.LatLng(40.6700, -73.9400), // New York
// How you would like to style the map.
// This is where you would paste any style found on Snazzy Maps.
styles: [{"featureType":"all","elementType":"geometry.fill","stylers":[{"weight":"2.00"}]},{"featureType":"all","elementType":"geometry.stroke","stylers":[{"color":"#9c9c9c"}]},{"featureType":"all","elementType":"labels.text","stylers":[{"visibility":"on"}]},{"featureType":"landscape","elementType":"all","stylers":[{"color":"#f2f2f2"}]},{"featureType":"landscape","elementType":"geometry.fill","stylers":[{"color":"#ffffff"}]},{"featureType":"landscape.man_made","elementType":"geometry.fill","stylers":[{"color":"#ffffff"}]},{"featureType":"poi","elementType":"all","stylers":[{"visibility":"off"}]},{"featureType":"road","elementType":"all","stylers":[{"saturation":-100},{"lightness":45}]},{"featureType":"road","elementType":"geometry.fill","stylers":[{"color":"#eeeeee"}]},{"featureType":"road","elementType":"labels.text.fill","stylers":[{"color":"#7b7b7b"}]},{"featureType":"road","elementType":"labels.text.stroke","stylers":[{"color":"#ffffff"}]},{"featureType":"road.highway","elementType":"all","stylers":[{"visibility":"simplified"}]},{"featureType":"road.arterial","elementType":"labels.icon","stylers":[{"visibility":"off"}]},{"featureType":"transit","elementType":"all","stylers":[{"visibility":"off"}]},{"featureType":"water","elementType":"all","stylers":[{"color":"#46bcec"},{"visibility":"on"}]},{"featureType":"water","elementType":"geometry.fill","stylers":[{"color":"#c8d7d4"}]},{"featureType":"water","elementType":"labels.text.fill","stylers":[{"color":"#070707"}]},{"featureType":"water","elementType":"labels.text.stroke","stylers":[{"color":"#ffffff"}]}]
};
// Get the HTML DOM element that will contain your map
// We are using a div with id="map" seen below in the <body>
var mapElement = document.getElementById('map');
// Create the Google Map using our element and options defined above
var map = new google.maps.Map(mapElement, mapOptions);
// Let's also add a marker while we're at it
var marker = new google.maps.Marker({
position: new google.maps.LatLng(40.6700, -73.9400),
map: map,
title: 'Snazzy!'
});
}
</script>
</head>
<body>
<h1>Snazzy Maps Super Simple Example</h1>
<h2>WY</h2>
<!-- The element that will contain our Google Map. This is used in both the Javascript and CSS above. -->
<div id="map"></div>
</body>
</html>
To set the style using Gmaps library, you need to define the styles and then set it to the current map as below:
const map = new GMaps({ el: '#map', lat: 0, lng: 0 });
var styles = [
{
stylers: [
{ hue: "#00ffe6" },
{ saturation: -20 }
]
}, {
featureType: "road",
elementType: "geometry",
stylers: [
{ lightness: 100 },
{ visibility: "simplified" }
]
}, {
featureType: "road",
elementType: "labels",
stylers: [
{ visibility: "off" }
]
}
];
map.addStyle({
styledMapName:"Styled Map",
styles: styles,
mapTypeId: "map_style"
});
map.setStyle("map_style");
Reference:
https://github.com/hpneo/gmaps/blob/master/examples/styled_maps.html

React Bootstrap OverlayTrigger with trigger="focus" bug work around

In iOS safari, OverlayTrigger with trigger="focus" isn't able to dismiss when tapping outside. Here is my code:
<OverlayTrigger
trigger="focus"
placement="right"
overlay={ <Popover id="popoverID" title="Popover Title">
What a popover...
</Popover> } >
<a bsStyle="default" className="btn btn-default btn-circle" role="Button" tabIndex={18}>
<div className="btn-circle-text">?</div>
</a>
</OverlayTrigger>
I know that this is a known bug for Bootstrap cuz this doesn't even work on their own website in iOS, but does anyone know any method to go around it? It would be the best if it is something that doesn't require jQuery, but jQuery solution is welcome. Thanks.
OK, since no one else gives me a work around, I worked on this problem with my co-worker together for 3 days, and we came up with this heavy solution:
THE PROBLEM:
With trigger="focus", Bootstrap Popover/Tooltip can be dismissed when CLICKING outside the Popover/Tooltip, but not TOUCHING. Android browsers apparently changes touches to clicks automatically, so things are fine on Android. But iOS safari and browsers that is based on iOS safari (iOS chrome, iOS firefox, etc...) don't do that.
THE FIX:
We found out that in React Bootstrap, the Overlay component actually lets you customize when to show the Popover/Tooltip, so we built this component InfoOverlay based on Overlay. And to handle clicking outside the component, we need to add event listeners for both the Popover/Tooltip and window to handle both 'mousedown' and 'touchstart'. Also, this method would make the Popover have its smallest width all the time because of the padding-right of the component is initially 0px, and we make based on the width of some parent component so that it is responsive based on the parent component. And the code looks like this:
import React, { Component, PropTypes as PT } from 'react';
import {Popover, Overlay} from 'react-bootstrap';
export default class InfoOverlay extends Component {
static propTypes = {
PopoverId: PT.string,
PopoverTitle: PT.string,
PopoverContent: PT.node,
// You need to add this prop and pass it some numbers
// if you need to customize the arrowOffsetTop, it's sketchy...
arrowOffsetTop: PT.number,
// This is to be able to select the parent component
componentId: PT.string
}
constructor(props) {
super(props);
this.state = {
showPopover: false,
popoverClicked: false
};
}
componentDidMount() {
// Here are the event listeners and an algorithm
// so that clicking popover would not dismiss itself
const popover = document.getElementById('popoverTrigger');
if (popover) {
popover.addEventListener('mousedown', () => {
this.setState({
popoverClicked: true
});
});
popover.addEventListener('touchstart', () => {
this.setState({
popoverClicked: true
});
});
}
window.addEventListener('mousedown', () => {
if (!this.state.popoverClicked) {
this.setState({
showPopover: false
});
} else {
this.setState({
popoverClicked: false
});
}
});
window.addEventListener('touchstart', () => {
if (!this.state.popoverClicked) {
this.setState({
showPopover: false
});
} else {
this.setState({
popoverClicked: false
});
}
});
// this is to resize padding-right when window resizes
window.onresize = ()=>{
this.setState({});
};
}
// This function sets the style and more importantly, padding-right
getStyle() {
if (document.getElementById(this.props.componentId) && document.getElementById('popoverTrigger')) {
const offsetRight = document.getElementById(this.props.componentId).offsetWidth - document.getElementById('popoverTrigger').offsetLeft - 15;
return (
{display: 'inline-block', position: 'absolute', 'paddingRight': offsetRight + 'px'}
);
}
return (
{display: 'inline-block', position: 'absolute'}
);
}
overlayOnClick() {
this.setState({
showPopover: !(this.state.showPopover)
});
}
render() {
const customPopover = (props) => {
return (
{/* The reason why Popover is wrapped by another
invisible Popover is so that we can customize
the arrowOffsetTop, it's sketchy... */}
<div id="customPopover">
<Popover style={{'visibility': 'hidden', 'width': '100%'}}>
<Popover {...props} arrowOffsetTop={props.arrowOffsetTop + 30} id={this.props.PopoverId} title={this.props.PopoverTitle} style={{'marginLeft': '25px', 'marginTop': '-25px', 'visibility': 'visible'}}>
{this.props.PopoverContent}
</Popover>
</Popover>
</div>
);
};
return (
<div id="popoverTrigger" style={this.getStyle()}>
<a bsStyle="default" className="btn btn-default btn-circle" onClick={this.overlayOnClick.bind(this)} role="Button" tabIndex={13}>
<div id="info-button" className="btn-circle-text">?</div>
</a>
<Overlay
show={this.state.showPopover}
placement="right"
onHide={()=>{this.setState({showPopover: false});}}
container={this}>
{customPopover(this.props)}
</Overlay>
</div>
);
}
}
In the end, this is a heavy work around because it is a big amount of code for a fix, and you can probably feel your site is slowed down by a tiny bit because of the 4 event listeners. And the best solution is just tell Bootstrap to fix this problem...

How to integrate the Twitter widget into Reactjs?

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

Resources