I used react.js in my new project and found that javascript didn't work when I used ReactDOM to render class extended from React.Component
When script which fire alert() method is used as last it does not works.
When I change order of scripts, they work.
<div id="root"></div>
<div id="hello"><div>
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<script>
class HelloReact extends React.Component {
render() {
return React.createElement("div", null, React.createElement("h1", null, "Hello world 1!"));
}
}
ReactDOM.render(React.createElement(HelloReact, null), document.getElementById("hello"));
ReactDOM.render(React.createElement("h1", null, "Hello, world 2!"), document.getElementById('root'));
</script>
<script>alert("Hello");</script>
I would know is it normal (and I should not use javascript code after scripts with react code) or there is a bug in react library?
I was checking in Dev Tools and wasn't see any errors. I added files to github [ https://github.com/darekjk/reactjs_examples/tree/master/react-js-problem-20181231 ] to be sure I didn't make any error in copy/paste.
If you see javascript simply not executing, you 99% have a javascript error occuring before.
Interestingly your code does run on both my local machine and JsFiddle.
But if it still has problems in your specific scenario, start with opening up Chrome Dev Tools (F12) and look at the Console for any JavaScript errors.
Ouch, I spotted the actual error here, it's a funny one.
Take a look at this line: <div id="hello"><div>.
You meant to write <div id="hello"></div> but missed the slash.
This means that all your tags after that line are inside the hello div (and the other unnamed div that was supposed to be a closing tag). You can check it in the Elements view of Chrome Dev Tools.
This means that when ReactDOM renders your class into the hello div, it overwrites everything, because everything is inside the hello div, including itself and that other script tag. In the screenshot above you can see that all the script tags are missing.
Related
I'm trying to generalize my code by keeping a .js file containing only React components in one file and then utilizing these components in an HTML file. Here is my simple component:
component.js
'use strict'
class MyComponent extends React.Component {
render() {
return (
<div className="MyComponent">
<p>Text goes here.</p>
</div>
);
}
}
If in my component.js file I add: ReactDOM.render(<MyComponent/>, document.querySelector('#div-1')); and then, in my HTML, add <script src="component.js" type="text/jsx"></script> the React component shows in my page as expected.
However, my end goal is to be able to add the ReactDOM.render into my HTML within a script tag, that way I can have multiple pages utilizing the component.js components while doing all the assigning in the HTML page. Something like:
mypage.html (simplified)
<!DOCTYPE html>
<html>
<script src="component.js" type="text/jsx"></script> //import my components (no assigning done in this file)
<div id="div-1"><div>
<script>
ReactDOM.render(<MyComponent/>, document.querySelector('#div-1')); //assign to div
</script>
</html>
However this above code fails, with many errors regarding Uncaught SyntaxError: Unexpected token '<'
With that, how would I go about carrying something like this out? Any help is greatly appreciated.
The issue you're facing is that JSX isn't recognized by default in a browser.
Uncaught SyntaxError: Unexpected token '<' that's what this error means.
React docs have following help regarding that: quickly try JSX
you need to add babel in script tags and add type="text/babel" in whichever script you're using JSX.
<div id="counter_container"></div>
<!-- add babel support -->
<script src="https://unpkg.com/babel-standalone#6/babel.min.js"></script>
<!-- Load our React component. -->
<script src="components.js"></script>
<script type="text/babel">
(() => {
const Counter = window.Counter;
const counterContainerEl = document.querySelector('#counter_container');
ReactDOM.render(<Counter/>, counterContainerEl);
})();//this is just to avoid polluting global scope
</script>
I've put together a short example here github-repo
I have two html files(index.html and project.html), index.html contain or needs two javascript files(main.js and index.js).
The main.js contains the functions that both html files needs. And the index.js has the functons that only index.html needs.
So am saying index.html-->(main.js,index.js) and project.html-->(main.js).
The issue is that when I open the project.html the DOM elements that I called in index.js is throwing errors saying that the element is null.
The thing is that the DOM element that is causing the error is only created in index.html and not project.html but project is not supposed to call or know that function.
index.html
<script src="asset/javaScript/javaScript_for_index/main.js" defer type="module"></script>
<script src="asset/javaScript/javaScript_for_index/index.js" defer type="module"></script>
project.html
<script src="asset/javaScript/javaScript_for_index/main.js" defer type="module"></script>
This is where i get the error in the inspector. Note that the error comes from the project.html and it is caused by the index.js
I know that this is a bit confusing but this is the best i can explain it.
Thanks in advance!
Two things:
Note that all your <script> elements should appear in your markup before the closing </body> element.
On each page, only reference the <script>(s) that you need for that page
Example:
index.html
<script src="main.js"></script>
<script src="index.js"></script>
</body>
</html>
project.html
<script src="main.js"></script>
</body>
</html>
Example:
index.html needs main.js and index.js
project.html needs A CERTAIN function in main.js ONLY
so main.js
function functionsThatIndexNeeds() {
alert('Im in index.html!!!');
}
function functionsThatProjectNeeds() {
alert('IM IN PROJECTS~~~');
}
index.html
<script>functionsThatIndexNeeds()</script>
projects.html
<script>functionsThatProjectNeeds</script>
The point is to call ONLY the functions that each HTML files need.
Tell me if this works on you!:)
Before we do anything start with clearing your cache. (Important)
If you are sure that you have done everything right, just like #Rounin answer suggest,
Then run your code again, inspect to make sure your error is coming from index.js and if it is, then you are somehow injecting index.js into the page without knowing , (maybe somewhere at the middle of your body or something else), you might have to do a more thorough debugging than just asking. And most probably you have not told us everything because you might not be aware of it.
Try searching for any occurrence of index.js on your project.html script. (Ctrl+F)
Now if all else fails and you have to move on fast, then u can try this hack on your index.html and index.js script.
Index.html
<script> var page = "index" </script>
Put this on line 1, before anything else, because I don't know what line might be caising your problem
Then on index.js wrap your codes with an if statement (i.e put if statements to check if the page = "index" to prevent unwanted codes from running on other pages
E.g:
If (typeof page !== undefined && page == "index") {
// allow code to execute
}
This is a dirty hack, but it might kept you going until you get a more experience engineer to debug your codes...
Obviously, you must have something in main.js that is referencing DOM parts that are in index.html. Stop referencing those, and you'll be okay. Note, that if I have a DIV in index.html with ID foo which project.html does not have, then you can use document.querySelectorAll() function to check if that element exists (can look at length, returned from that, as well as other options like undefined), and then react if it doesn't exist. That can help you delineate items from index.html versus project.html.
In our project we've previously been using Thymeleaf, but now that we're moving over to Vue.js, we're experiencing some issues using the same ad scripts. The scripts look like this. I've only altered the URLs.
<script data-adfscript="sub.adcompany.net/asdf/?id=256746"></script>
<script src="//sub.adcompany.net/url/to/advertisement/script.js" async="async" defer="defer"></script>
If we put these tags in the <template>, Webpack gives the following message:
Templates should only be responsible for mapping the state to the UI.
Avoid placing tags with side-effects in your templates, such as
, as they will not be parsed.
So I've then been Googling all over to find a similar case. There are some plugins that do this for Google Ads, but they won't work for us. Escaping the script tags <\/script> works in a way, but then the script isn't added to the DOM until after loaded, and so it doesn't run.
Has anyone run into similar issues? If so, what was your solution?
Vue file looks something like this:
<template>
<aside class="sidebar-ad ui-wide">
<script data-adfscript="sub.adcompany.net/asdf/?id=256746"></script>
<script src="//sub.adcompany.net/url/to/advertisement/script.js" async="async" defer="defer"></script>
</aside>
</template>
<script>
export default {
data () {
return {}
}
}
</script>
There is a workaround. Works with style tag too.
<component is="script" src="https://www.example.com/example.js" async></component>
You should not treat Vue templates as a your final HTML, although their syntax is nearly identical and is also HTML-syntax compliant.
Templates are just a UI scaffolds for the data (that is why it is called a data-driven paradigm). They get parsed and transformed into render functions that in the end will produce the final and reactive DOM tree. During this process the <script> tags are indeed ommited cause it is not a place for any logic to happen.
However if you really need to embed any 3rd party script within your component there is a neat way to do this.
First, create container for the script:
<template>
<div id="component-root">
<!-- (...) -->
<div v-el:script-holder></div>
</div>
</template>
Then dynamicly create <script> tag and insert it directly to the DOM tree (using pure Vanilla JS):
<script>
export default {
data () {
return {};
},
ready() {
let scriptEl = document.createElement('script');
scriptEl.setAttribute('src', 'https://cdn.com/somescript.js');
scriptEl.setAttribute('data-some-param', 'paramvalue');
this.$els.scriptHolder.appendChild(scriptEl);
},
}
</script>
The this.$els.scriptHolder returns actual DOM element, calling the appendChild() forces the browser to insert DOM node and run the script just like during ordinary HTML code rendering.
Instead of $els you could also use $el which would return the components root DOM element (in this example the <div id="component-root">) or even the $root.$el which would return the Vue App root DOM element.
Note that this.$els is a Vue 1 feature, which has been replaced with $refs in Vue 2: https://v2.vuejs.org/v2/guide/migration.html#v-el-and-v-ref-replaced
You can try with this package
https://www.npmjs.com/package/vue-script2
I made a vue component to handle script loading within the template tags.
Personally, I use it to load ads in my vuejs apps.
here:
https://github.com/TheDynomike/vue-script-component
I found a way to work around this, not sure how well it works but this the way I did it.
Run the <script> in normal html then go to Dev tools and copy the iframe code made by the script and then paste it into the code as iframe instead of the <script>.
just place your in vue template scripts after your app, in exemple at the end of the body
(function($) {
$('#your-app').find('script').appendTo('body')
<script> your vue script (create app)</script>
})(jQuery);
I am unable to get this simple class to render. Here is my code.
allView.js
var StatCard = React.createClass({
render: function() {
return (
<div class="card">
<div class="ui statistic">
<div class="value">4480</div>
</div>
<div class="header">Schools</div>
<div class = "meta">matcher</div>
</div>
);
}
});
// console.log("Before ReactDOM.render"); -> It doesn't log anything
ReactDOM.render( <StatCard />, document.getElementById('chartarea'));
HTML File
<div id="chartarea"> </div>
</body>
<script type="text/jsx" src="static/js/all/allView.js"></script>
I'm relatively new to JS so am unable to do much. I did the following after reading similar questions and the documentation
Capitalized variable
Added type="text/jsx" to the script tag
Tried using type="text/babel" instead
Placed the script tag at different places even though placing it at the end seems appropriate
Checked and rechecked closing tags on the element it replaces.
Included relevant React files as given in their demo fiddle.
Checked the console (all files load with with a status code of 200)
I placed a console.log statement without the comments and yet nothing shows up on my console.
Any help is greatly appreciated.
Did you included babel script? And how?
Add script type="text/babel" JS FIDDLE
<script type="text/babel" src="static/js/all/allView.js"></script>
I am rendering in the browser an HTML page which references a react class.
Unfortunately, I am getting this error:
Uncaught SyntaxError: Unexpected token <
On the third line of the following function (the <div> statement).
render: function() {
return (
<div>
<h1>Res</h1>
<resE data={this.state.data} />
</div>
);
It appears that the JSX is not transformed properly.
However, I am referencing JSXTransformer in the HTML file:
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.0/JSXTransformer.js"></script>
Furthermore, I tried adding the following line at the top of the file containing the react class:
/** #jsx React.DOM */
However, the error persisted.
Can you show the script that your code sits in?
I believe your issue is that you need to make sure that script has the attribute
type="text/jsx"
so to solve your issue do this;
<script type="text/jsx" src="app/restrictions/Main.js"></script>
Your JSX compiler script looks for any scripts that have that text/jsx attribute to know that it needs to turn that JSX code to raw JavaScript.