score:684
edit: things change fast and this is outdated - see update
do you want to fetch and execute the script again and again, every time this component is rendered, or just once when this component is mounted into the dom?
perhaps try something like this:
componentdidmount () {
const script = document.createelement("script");
script.src = "https://use.typekit.net/foobar.js";
script.async = true;
document.body.appendchild(script);
}
however, this is only really helpful if the script you want to load isn't available as a module/package. first, i would always:
- look for the package on npm
- download and install the package in my project (
npm install typekit
) import
the package where i need it (import typekit from 'typekit';
)
this is likely how you installed the packages react
and react-document-title
from your example, and there is a typekit package available on npm.
update:
now that we have hooks, a better approach might be to use useeffect
like so:
useeffect(() => {
const script = document.createelement('script');
script.src = "https://use.typekit.net/foobar.js";
script.async = true;
document.body.appendchild(script);
return () => {
document.body.removechild(script);
}
}, []);
which makes it a great candidate for a custom hook (eg: hooks/usescript.js
):
import { useeffect } from 'react';
const usescript = url => {
useeffect(() => {
const script = document.createelement('script');
script.src = url;
script.async = true;
document.body.appendchild(script);
return () => {
document.body.removechild(script);
}
}, [url]);
};
export default usescript;
which can be used like so:
import usescript from 'hooks/usescript';
const mycomponent = props => {
usescript('https://use.typekit.net/foobar.js');
// rest of your component
}
score:-3
you can put your script in an html file before react is being called.
score:-2
solution depends on scenario. like in my case, i had to load a calendly embed inside a react component.
calendly looks for a div and reads from it's data-url
attribute and loads an iframe inside the said div.
it is all good when you first load the page: first, div with data-url
is rendered. then calendly script is added to body. browser downloads and evaluates it and we all go home happy.
problem comes when you navigate away and then come back into the page. this time the script is still in body and browser doesn't re-download & re-evaluate it.
fix:
- on
componentwillunmount
find and remove the script element. then on re mount, repeat the above steps. - enter
$.getscript
. it is a nifty jquery helper that takes a script uri and a success callback. once the script it loaded, it evaluates it and fires your success callback. all i have to do is in mycomponentdidmount
$.getscript(url)
. myrender
method already has the calendly div. and it works smooth.
score:-2
i saw the same problem, until i found this package, quite easy to implement, i hope it works as it worked for me :)
https://github.com/gumgum/react-script-tag
import react from 'react';
import script from '@gumgum/react-script-tag';
import './app.css';
function app() {
return (
<div >
<h1> graphs</h1>
<div class="flourish-embed flourish-network" data-src="visualisation/8262420">
<script src"your script"
</script>
</div>
</div>
);
}
export default app;
score:0
for multiple scripts, use this
var loadscript = function(src) {
var tag = document.createelement('script');
tag.async = false;
tag.src = src;
document.getelementsbytagname('body').appendchild(tag);
}
loadscript('//cdnjs.com/some/library.js')
loadscript('//cdnjs.com/some/other/library.js')
score:0
for a more complete usescript
implementation that supports loading status and error handling, check out this from usehooks.
usage
function app() {
const status = usescript(
"https://pm28k14qlj.codesandbox.io/test-external-script.js"
);
return (
<div>
<div>
script status: <b>{status}</b>
</div>
{status === "ready" && (
<div>
script function call response: <b>{test_script.start()}</b>
</div>
)}
</div>
);
}
hook
function usescript(src) {
// keep track of script status ("idle", "loading", "ready", "error")
const [status, setstatus] = usestate(src ? "loading" : "idle");
useeffect(
() => {
// allow falsy src value if waiting on other data needed for
// constructing the script url passed to this hook.
if (!src) {
setstatus("idle");
return;
}
// fetch existing script element by src
// it may have been added by another intance of this hook
let script = document.queryselector(`script[src="${src}"]`);
if (!script) {
// create script
script = document.createelement("script");
script.src = src;
script.async = true;
script.setattribute("data-status", "loading");
// add script to document body
document.body.appendchild(script);
// store status in attribute on script
// this can be read by other instances of this hook
const setattributefromevent = (event) => {
script.setattribute(
"data-status",
event.type === "load" ? "ready" : "error"
);
};
script.addeventlistener("load", setattributefromevent);
script.addeventlistener("error", setattributefromevent);
} else {
// grab existing script status from attribute and set to state.
setstatus(script.getattribute("data-status"));
}
// script event handler to update status in state
// note: even if the script already exists we still need to add
// event handlers to update the state for *this* hook instance.
const setstatefromevent = (event) => {
setstatus(event.type === "load" ? "ready" : "error");
};
// add event listeners
script.addeventlistener("load", setstatefromevent);
script.addeventlistener("error", setstatefromevent);
// remove event listeners on cleanup
return () => {
if (script) {
script.removeeventlistener("load", setstatefromevent);
script.removeeventlistener("error", setstatefromevent);
}
};
},
[src] // only re-run effect if script src changes
);
return status;
}
score:0
i had raw html string with javascript/jquery
i installed npm library dangerously-set-html-content
npm i dangerously-set-html-content
import innerhtml from 'dangerously-set-html-content'
<div>
<innerhtml html={html}/>
</div>
or
import innerhtml from 'dangerously-set-html-content'
const renderhtml=`<!doctype html><html lang="en"><head><meta charset="utf-8"><title> is not defined</title>$(document).ready(function(){ $("button").click(function(){ alert("jquery is working perfectly."); }); });</script></head><body> <button type="button">test jquery code</button></body></html>`
<div>
<innerhtml html={renderhtml}/>
</div>
make sure you add jquery cdn to public/index.html file
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-fgpcb/kjqllnfou91ta32o/nmzxltwro8qtmkmrdau8=" crossorigin="anonymous" async="true" ></script>
score:1
componentdidmount() {
const head = document.queryselector("head");
const script = document.createelement("script");
script.setattribute(
"src",
"https://assets.calendly.com/assets/external/widget.js"
);
head.appendchild(script);
}
score:1
just add in body in html file
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
score:1
honestly, for react - don't bother with messing around adding <script>
tags to your header. it's a pain in the ass to get a callback when they have loaded fully. instead, use a package like @charlietango/usescript to load the script when you need it and get a status update when it is completed.
example usage:
import react from 'react'
import usescript, { scriptstatus } from '@charlietango/use-script'
const component = () => {
const [ready, status] = usescript('https://api.google.com/api.js')
if (status === scriptstatus.error) {
return <div>failed to load google api</div>
}
return <div>google api ready: {ready}</div>
}
export default component
ps. if you're using redux to tell other components when your script has loaded, and are using redux-persist
like i was, don't forget to include a modifier on your redux-persist setup that always sets the script loaded redux value to false in the redux backup.
score:1
i recently faced the issue, tried multiple solutions given here, at last sattled with iframe, iframe seems to work seamlessly if it you are trying to integrate a js plugin on a specific screen
<iframe
id="xxx"
title="xxx"
width="xxx"
height="xxx"
frameborder="value"
allowtransparency
srcdoc={`
<!doctype html>
<html>
<head>
<title>chat bot</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
</head>
<body style="width:100%">
<script type="text/javascript">
......
</script>
</body>
</html>
`}
/>
score:2
a bit late to the party but i decided to create my own one after looking at @alex macmillan answers and that was by passing two extra parameters; the position in which to place the scripts such as or and setting up the async to true/false, here it is:
import { useeffect } from 'react';
const usescript = (url, position, async) => {
useeffect(() => {
const placement = document.queryselector(position);
const script = document.createelement('script');
script.src = url;
script.async = typeof async === 'undefined' ? true : async;
placement.appendchild(script);
return () => {
placement.removechild(script);
};
}, [url]);
};
export default usescript;
the way to call it is exactly the same as shown in the accepted answer of this post but with two extra(again) parameters:
// first string is your url
// second string can be head or body
// third parameter is true or false.
usescript("string", "string", bool);
score:2
very similar to other answers just using default values to clean up undefined checks
import { useeffect } from 'react'
const usescript = (url, selector = 'body', async = true) => {
useeffect(() => {
const element = document.queryselector(selector)
const script = document.createelement('script')
script.src = url
script.async = async
element.appendchild(script)
return () => {
element.removechild(script)
}
}, [url])
}
export default usescript
usage
usescript('/path/to/local/script.js') // async on body
usescript('https://path/to/remote/script.js', 'html') // async on html
usescript('/path/to/local/script.js', 'html', false) // not async on html.. e.g. this will block
score:3
according to alex mcmillan's solution, i have the following adaptation.
my own environment: react 16.8+, next v9+
// add a custom component named script
// hooks/script.js
import { useeffect } from 'react'
// react-helmet don't guarantee the scripts execution order
export default function script(props) {
// ruels: alwasy use effect at the top level and from react functions
useeffect(() => {
const script = document.createelement('script')
// src, async, onload
object.assign(script, props)
let { parent='body' } = props
let parentnode = document.queryselector(parent)
parentnode.appendchild(script)
return () => {
parentnode.removechild(script)
}
} )
return null // return null is necessary for the moment.
}
// use the custom compoennt, just import it and substitute the old lower case <script>
tag with the custom camel case <script>
tag would suffice.
// index.js
import script from "../hooks/script";
<fragment>
{/* google map */}
<div ref={el => this.el = el} classname="gmap"></div>
{/* old html script */}
{/*<script type="text/javascript" src="http://maps.google.com/maps/api/js"></script>*/}
{/* new custom script component */}
<script async={false} type="text/javascript" src='http://maps.google.com/maps/api/js' />
</fragment>
score:4
you can find best answer at the following link:
const loaddynamicscript = (callback) => { const existingscript = document.getelementbyid('scriptid'); if (!existingscript) { const script = document.createelement('script'); script.src = 'url'; // url for the third-party library being loaded. script.id = 'libraryname'; // e.g., googlemaps or stripe document.body.appendchild(script); script.onload = () => { if (callback) callback(); }; } if (existingscript && callback) callback(); };
score:4
to add script tag or code in head tag <head>
, use react-helmet package. it is light and have good documentation.
to add js code in script tag inside body,
function htmldecode(html) {
return html.replace(/&([a-z]+);/ig, (match, entity) => {
const entities = { amp: '&', apos: '\'', gt: '>', lt: '<', nbsp: '\xa0', quot: '"' };
entity = entity.tolowercase();
if (entities.hasownproperty(entity)) {
return entities[entity];
}
return match;
});
}
render() {
const scriptcode = `<script type="text/javascript">
{(function() {
window.hello={
first_name: 'firstname',
last_name: 'lastname',
};
})()}
</script>`
return(
<div dangerouslysetinnerhtml={{ __html: this.htmldecode(scriptcode) }} />;
);
}
this code can be tested by console.log(windows.hello)
score:4
here is how i was finally able to add two external javascript files in my react js code:
these are the steps i followed.
step 1:
i installed react-helmet using npm i react-helmet
from the terminal while inside my react-app folder path.
step 2:
i then added import {helmet} from "react-helmet";
header in my code.
step 3: finally, in my code this is how i added the external js files using helment
<helmet>
<script src = "path/to/my/js/file1.js" type = "text/javascript" />
<script src = "path/to/my/js/file2.js" type = "text/javascript" />
</helmet>
score:5
you can use npm postscribe
to load script in react component
postscribe('#mydiv', '<script src="https://use.typekit.net/foobar.js"></script>')
score:7
there is a very nice workaround using range.createcontextualfragment
.
/**
* like react's dangerouslysetinnerhtml, but also with js evaluation.
* usage:
* <div ref={setdangeroushtml.bind(null, html)}/>
*/
function setdangeroushtml(html, el) {
if(el === null) return;
const range = document.createrange();
range.selectnodecontents(el);
range.deletecontents();
el.appendchild(range.createcontextualfragment(html));
}
this works for arbitrary html and also retains context information such as document.currentscript
.
score:8
i created a react component for this specific case: https://github.com/coreyleelarson/react-typekit
just need to pass in your typekit kit id as a prop and you're good to go.
import react from 'react';
import typekit from 'react-typekit';
const htmllayout = () => (
<html>
<body>
<h1>my example react component</h1>
<typekit kitid="abc123" />
</body>
</html>
);
export default htmllayout;
score:11
i tried to edit the accepted answer by @alex mcmillan but it won't let me so heres a separate answer where your able to get the value of the library your loading in. a very important distinction that people asked for and i needed for my implementation with stripe.js.
usescript.js
import { usestate, useeffect } from 'react'
export const usescript = (url, name) => {
const [lib, setlib] = usestate({})
useeffect(() => {
const script = document.createelement('script')
script.src = url
script.async = true
script.onload = () => setlib({ [name]: window[name] })
document.body.appendchild(script)
return () => {
document.body.removechild(script)
}
}, [url])
return lib
}
usage looks like
const paymentcard = (props) => {
const { stripe } = usescript('https://js.stripe.com/v2/', 'stripe')
}
note: saving the library inside an object because often times the library is a function and react will execute the function when storing in state to check for changes -- which will break libs (like stripe) that expect to be called with specific args -- so we store that in an object to hide that from react and protect library functions from being called.
score:12
you can also use react helmet
import react from "react";
import {helmet} from "react-helmet";
class application extends react.component {
render () {
return (
<div classname="application">
<helmet>
<meta charset="utf-8" />
<title>my title</title>
<link rel="canonical" href="http://example.com/example" />
<script src="/path/to/resource.js" type="text/javascript" />
</helmet>
...
</div>
);
}
};
helmet takes plain html tags and outputs plain html tags. it's dead simple, and react beginner friendly.
score:17
the answer alex mcmillan provided helped me the most but didn't quite work for a more complex script tag.
i slightly tweaked his answer to come up with a solution for a long tag with various functions that was additionally already setting "src".
(for my use case the script needed to live in head which is reflected here as well):
componentwillmount () {
const script = document.createelement("script");
const scripttext = document.createtextnode("complex script with functions i.e. everything that would go inside the script tags");
script.appendchild(scripttext);
document.head.appendchild(script);
}
score:22
if you need to have <script>
block in ssr (server-side rendering), an approach with componentdidmount
will not work.
you can use react-safe
library instead.
the code in react will be:
import safe from "react-safe"
// in render
<safe.script src="https://use.typekit.net/foobar.js"></safe.script>
<safe.script>{
`try{typekit.load({ async: true });}catch(e){}`
}
</safe.script>
score:31
this answer explains the why behind this behavior.
any approach to render the script
tag doesn't work as expected:
- using the
script
tag for external scripts - using
dangerouslysetinnerhtml
why
react dom (the renderer for react on web) uses createelement
calls to render jsx into dom elements.
createelement
uses the innerhtml
dom api to finally add these to the dom (see code in react source). innerhtml
does not execute script
tag added as a security consideration. and this is the reason why in turn rendering script
tags in react doesn't work as expected.
for how to use script
tags in react check some other answers on this page.
score:74
further to the answers above you can do this:
import react from 'react';
export default class test extends react.component {
constructor(props) {
super(props);
}
componentdidmount() {
const s = document.createelement('script');
s.type = 'text/javascript';
s.async = true;
s.innerhtml = "document.write('this is output by document.write()!')";
this.instance.appendchild(s);
}
render() {
return <div ref={el => (this.instance = el)} />;
}
}
the div is bound to this
and the script is injected into it.
demo can be found on codesandbox.io
score:86
my favorite way is to use react helmet – it's a component that allows for easy manipulation of the document head in a way you're probably already used to.
e.g.
import react from "react";
import {helmet} from "react-helmet";
class application extends react.component {
render () {
return (
<div classname="application">
<helmet>
<script src="https://use.typekit.net/foobar.js"></script>
<script>try{typekit.load({ async: true });}catch(e){}</script>
</helmet>
...
</div>
);
}
};
Source: stackoverflow.com
Related Query
- Adding JS script tag to React
- Adding variable to script tag in React
- Adding script tag to React/JSX
- Dynamic tag name in React JSX
- Tag Error: React JSX Style Tag Error on Render
- Formatting code with <pre> tag in React and JSX
- Dynamic href tag React in JSX
- Adding a new line in a JSX string inside a paragraph - React
- Facing issue while adding radio button in react - input is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`
- Add ld+json script tag in client-side React
- React Syntax Error : Expected corresponding JSX closing tag for <img>
- Adding React-Redux to a React app with React.StrictMode tag
- Custom HTML Element Tag within React JSX
- Render script tag in React Component
- how to to insert TradingView widget into react js which is in script tag link: https://www.tradingview.com/widget/market-overview/
- React - Create tag dynamically from ES6 template literal with JSX
- React - Converting HTML script tag to load an SDK asynchronously
- accessing variable from script tag in html file in react component
- React Native: How to add script tag in the component
- How do i dynamically create JSX tag in React using typescript?
- Adding external javascript script to React
- JSX passing an object to the value of a jsx tag in React
- Adding script tag to Gatsby using helmet throws syntax errors
- Adding Transition Effect to JSX Component in React
- Divider Disappears When Adding Floated Tag on Vertical Menu Semantic UI React
- React component bundled as an UMD can't load a dependency when imported via script tag in another react app
- Unable to write script tag which includes some code in React Component
- React | render html tag in jsx
- Automatic script conversion js to jsx in react app
- React Router Renders Empty Script Tag
More Query from same tag
- How do I solve: "TypeError: Cannot read property 'map' of undefined"
- How to maximize performance in React when taking controlled input from multiple components?
- How to fill array of boolean values on checkbox change event?
- Why does the 'same' code looks different in the same browser with the same size, where one deployment is on localhost and the other remote
- Is dispatch function returned from useDispatch hook synchronous with async thunk?
- Unable to load the store in redux with some static data
- Controlled Select in React not setting defaultValue
- Make Axios Limit the Number of Responses
- On firebase DB, Redux duplicate last data from store
- Uploading profile pic with react.js node.js express.js REST API to sqlite DB
- Specify multiple reversed criteria for grid
- How to process data received from an AJAX request in React
- How to notify user that someone is writing in the same room?
- React - how to delete an item from table
- Can't display an image in react from backend django
- Material Ui DataGrid IsRowSelectable not working in React ts
- 'npm start' Taking way too long
- Does react have a markup binding syntax?
- Showing a react component on click
- Display Firestore Data with a datatype of map: Error: Objects are not valid as a React child
- How to use a callback function in OnClick in react
- what is this difference between this flux action and this function call?
- Unable to update collection
- React datepicker - invalid time value
- How to get and render points from a database firebase
- Should I use props or states in order to pass data?
- Why is _this.state.searchAddress() not a function?
- How can I calculate the differences between now date and constant date. And edit it like 1d,1m,1w
- Can't figure out how change css using props in styled components and a useState hook
- How to pass dynamic id and hence dynamic toggler to UncontrolledCollapse tag of Reactstrap?