Simple React component fails to render - javascript

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>

Related

import React Components to HTML

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

Bootstrap popover works on second load

I have made a webpage on Sharepoint with bootstrap and the content is populated with javascript. I am using popover in a table. The table is generated via javascript. The strange thing is that the popover works only after I made a refresh of the page/reloaded it with F5.
A popover outside of the table works fine and by first load. As well as the code runs fine without problems on my local machine, but on sharepoint it breaks down.
Here some code - initialization:
<script src="jquery-3.5.1.slim.min.js"></script>
<script src="popper.min.js"></script>
<script src="bootstrap.min.js"></script>
then the function for generating the table is called:
<body onload="javascript: GenerateTable();">
followed by the popper call:
$(function () {
$('.example-popover').popover({
})
})
The result is a table which contains the following line with the popper:
<td>Here is a question which needs a popper as info!
<div class="row justify-content-end">
Info
</div>
</td>
It seems to me like it an issue with the loading order - but can't figure out why it works locally but not on Sharepoint.
I import js from CDN, it works well in my environment.
Test code for your reference:
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<body >
<td>Here is a question which needs a popper as info!
<div class="row justify-content-end">
Info
</div>
</td>
</body>
<script>
$(function () {
$('.badge').popover();
})
</script>
Test result:
If you need further assistance,please share the full code.
The problem was the order of the javascript execution. As the code is loaded from an external javascript file the order how the code is loaded is not known.
Thus it is recommended to put the javascript function from the html file into an explicit function into the javascript file. Then the function has to be called explicitly.
Javascript File:
function PopperCall(){
$('.example-popover').popover({});
$('.popover-dismiss').popover({trigger: 'focus'});
$('[data-toggle="popover"]').popover();
}
In the HTML the loading is done by:
<body onload="javascript: GenerateTable(); PopperCall();">

How to querySelector an element in an html import from a document that imports it?

Let say I have a html document with this div inside :
div.html
<div class="thediv">
<h1>test</h1>
<p class="insert"></p>
</div>
from index.html, I import it
<link rel="import" href="/path/to/div.html">
Now If I type in the console or in a script
const div = document.querySelector('.thediv');
div is null, as if the div just vanished. But I am sure there is a way to select the element because some webcomponents libraries allow programmer to define their own custom elements one by file.
I tried many things but can't find the solution.
Thanks for the help.
update :
This is true for any HTML Elements (not just div). I just pick an example for the question.
You can reference the document set at <link> element with rel attribute set to "import" using .import property of <link> element, see also Is there a way to know if a link/script is still pending or has it failed, How to append a whole html file with jquery
document.querySelector("link[rel=import][href='template1.html']")
.import.querySelector("#template1")
Solution found here: https://www.html5rocks.com/en/tutorials/webcomponents/imports/
import.html
<template>
<h1>Hello World!</h1>
<!-- Img is not requested until the <template> goes live. -->
<img src="world.png">
<script>alert("Executed when the template is activated.");</script>
</template>
index.html
<head>
<link rel="import" href="import.html">
</head>
<body>
<div id="container"></div>
<script>
var link = document.querySelector('link[rel="import"]');
// Clone the <template> in the import.
var template = link.import.querySelector('template');
var clone = document.importNode(template.content, true);
document.querySelector('#container').appendChild(clone);
</script>
</body>
I had 2 nice answers on my question and they helped me to find a more suitable solution for my specific problem I'm sharing here.
Again what I tried to achieve was to querySelector an element defined in an html import from the main document (i.e. index.html).
If we write something like
<div id="thediv">
...
</div>
at the root of an html import, the element won't be included in the body of the main document (I think each document has its own namespace or something like that).
#guest271314 recommended to use the import property of a link element to access the content of the fetched resource but see my comment on the same post. I think this is not really neat when you deal with documents that imports other documents that imports others...
#MaxBilbow recommended the same method providing a link and an example chunk using template. Again this is not really nice when you deal with relational imports. But the link gave me the solution.
In my imported document, I write an additional script :
div.html
<div id="thediv">
...
</div>
<script>
document.body.prepend(
document.currentScript.ownerDocument.querySelector('#thediv'));
</script>
Now when the html import is fetched the script will get executed and prepend the html chunk into the body of the main document.
index.html
<link rel="import" href="div.html">
<script>
// now I can querySelector('#thediv')
</script>
This is just an example and it is a dummy one, but I think I will mostly use that technique for templates, templates are hidden and it's ok to prepend them to the main document.
If you think that method could have flaws, please comment.
HTML Imports is deprecated and has now been removed as of M80. See https://www.chromestatus.com/features/5144752345317376 and https://developers.google.com/web/updates/2019/07/web-components-time-to-upgrade for more details.
You ca use fetch() to import your web component
How to separate web components to individual files and load them?

AngularJS complains that initialization not defined for jquery

I am getting the below error when loading my page.
Error: initialize is not defined
#http://localhost:8082/js/vendor/jquery-1.11.2.js line 339 > eval:4:3
I want to replace the jqLite with the full version of jquery. I have read several stackoverflow questions on this subject and they imply that all that is required is to load jquery before angularjs. I have done this by simply moving the declaration for jquery above the angular.js. When I do this that is when the above error occurs. It does not give the error when I move the jquery below angularjs but then I cannot use such things as angular.element.
What am I doing wrong?
As far as loading the javascript for each library all I am doing is.
<script type='text/javascript' src="js/vendor/jquery-1.11.2.js"></script>
<script type='text/javascript' src="js/vendor/angular.js"></script>
as far as using jquery instead of lqlite, I am simply trying to use angular.element
var someElement = angular.element('#someelement');
I read a blurb to load jquery before DOMContentLoaded. I am not sure how to do this. I know how to write an event handler for DOMContentLoaded, but what do I do then.
Edited answer: I usually inject my JS script code in the header all inside of an IFFE. You'd also have to make sure you have the ng-app in there to specify the module. Finally I've made sure I actually include the dependent code in the header before my code.
See fiddle here
<head>
<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.js"></script>
<script>
(function() {
var testApp = angular.module("testApp", []);
function SomeController($scope) {
console.log('Started controller');
$scope.dirPanelElement = angular.element('#some-panel');
$scope.dirPanelElement.text('set test');
$scope.dirPanelElementText='got "'+$scope.dirPanelElement.text()+'" from panel'
}
testApp.controller("SomeController", SomeController);
})(); // IFFE
</script>
</head>
<body ng-app='testApp'>
<div id="content">
<div style="padding:50px">
<div data-ng-controller="SomeController">
<p align="center">Something</p>
<div id="some-panel"></div>
<div id="some-canvas">{{dirPanelElementText}}</div>
</div>
</div>
</div>
</body>

React Error: Target Container is not a DOM Element

I just got started using React, so this is probably a very simple mistake, but here we go. My html code is very simple:
<!-- base.html -->
<html>
<head>
<title>Note Cards</title>
<script src="http://<url>/react-0.11.2.js"></script>
<!-- <script src="http://<url>/JSXTransformer-0.11.2.js"></script> -->
<script src="http://code.jquery.com/jquery-1.10.0.min.js"></script>
{% load staticfiles %}
<link rel="stylesheet" type="text/css" href="{% static "css/style.css" %}">
<script src="{% static "build/react.js" %}"></script>
</head>
<body>
<h1 id="content">Note Cards</h1>
<div class="gotcha"></div>
</body>
</html>
Note that I am using Django's load static files here. (My JavaScript is a bit more complex, so I won't post it all here unless someone requests it.) This is the line with the error:
React.renderComponent(
CardBox({url: "/cards/?format=json", pollInterval: 2000}),
document.getElementById("content")
);
After which I get the 'target container is not a DOM element error' yet it seems that document.getElementById("content") is almost certainly a DOM element.
I looked at this stackoverflow post, but it didn't seem to help in my situation.
Anyone have any idea why I'd be getting that error?
I figured it out!
After reading this blog post I realized that the placement of this line:
<script src="{% static "build/react.js" %}"></script>
was wrong. That line needs to be the last line in the <body> section, right before the </body> tag. Moving the line down solves the problem.
My explanation for this is that react was looking for the id in between the <head> tags, instead of in the <body> tags. Because of this it couldn't find the content id, and thus it wasn't a real DOM element.
Also make sure id set in index.html is same as the one you referring to in index.js
index.html:
<body>
<div id="root"></div>
<script src="/bundle.js"></script>
</body>
index.js:
ReactDOM.render(<App/>,document.getElementById('root'));
webpack solution
If you got this error while working in React with webpack and HMR.
You need to create template index.html and save it in src folder:
<html>
<body>
<div id="root"></div>
</body>
</html>
Now when we have template with id="root" we need to tell webpack to generate index.html which will mirror our index.html file.
To do that:
plugins: [
new HtmlWebpackPlugin({
title: "Application name",
template: './src/index.html'
})
],
template property will tell webpack how to build index.html file.
Just to give an alternative solution, because it isn't mentioned.
It's perfectly fine to use the HTML attribute defer here. So when loading the DOM, a regular <script> will load when the DOM hits the script. But if we use defer, then the DOM and the script will load in parallel. The cool thing is the script gets evaluated in the end - when the DOM has loaded (source).
<script src="{% static "build/react.js" %}" defer></script>
Also, the best practice of moving your <script></script> to the bottom of the html file fixes this too.
I had encountered the same error with React version 16. This error comes when the Javascript that tries to render the React component is included before the static parent dom element in the html. Fix is same as the accepted answer, i.e. the JavaScript should get included only after the static parent dom element has been defined in the html.
For those that implemented react js in some part of the website and encounter this issue.
Just add a condition to check if the element exist on that page before you render the react component.
<div id="element"></div>
...
const someElement = document.getElementById("element")
if(someElement) {
ReactDOM.render(<Yourcomponent />, someElement)
}
Also you can do something like that:
document.addEventListener("DOMContentLoaded", function(event) {
React.renderComponent(
CardBox({url: "/cards/?format=json", pollInterval: 2000}),
document.getElementById("content")
);
})
The DOMContentLoaded event fires when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading.
One of the case I encountered the same error in a simple project. I hope the solution helps someone.
Below code snippets are sufficient to understand the solution :
index.html
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
someFile.js : Notice the line const portalElement = document.getElementById("overlays"); below :
const portalElement = document.getElementById("overlays");
const Modal = (props) => {
return (
<Fragment>
      {ReactDOM.createPortal(<Backdrop />, portalElement)}
      
{ReactDOM.createPortal(
<ModalOverlay>{props.children}</ModalOverlay>,
portalElement
)}
    
</Fragment>
);
};
I didn't have any element with id = "overlays" in my index.html file, so the highlighted line above was outputting null and so React wasn't able to find inside which element it should create the portal i.e {ReactDOM.createPortal(<Backdrop />, portalElement)} so I got below error
I added the div in index.html file and the error was gone.
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="overlays"></div>
<div id="root"></div>
</body>
I got the same error i created the app with create-react-app but in /public/index.html also added matrialize script but there was to connection with "root" so i added
<div id="root"></div>
just before
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/ materialize.min.js"></script>
And it worked for me .
Target container is not a DOM element.
I achieved this error with a simple starter app also.
// index.js
ReactDOM.render(
<Router>
<App />,
document.getElementById('root')
</Router>
);
Solution:
Syntax errors can cause this error. I checked my syntax and wrapped my <App /> properly.
ReactDOM.render(
<Router>
<App />
</Router>,
document.getElementById('root')
);
In my case, I forget to add this line to the index.js file
document.getElementById('root')
and I forget to import react-dom import ReactDOM from 'react-dom'; so you can use ReactDOM later in the same file
Hope this will be helpful for you

Categories