React - Uncaught Error: Target container is not a DOM element - javascript

I'm new to react.
My error is:
Uncaught Error: Target container is not a DOM element
I've Googled this plenty of times and find people who have this error:
Uncaught Error: Invariant Violation: _registerComponent(...): Target container is not a DOM element.
Mine doesn't contain:
_registerComponent(...):
Here are my files:
index.html
<html>
<head>
<meta charset="utf-8">
<title>React</title>
</head>
<body>
<div id="root"></div>
<script src="./bundle.js"></script>
</body>
</html>
index.jsx
import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render(
<div>
<h1>Hello World!</h1>
</div>,
document.getElementById('root')
);
webpack.config.js
const path = require('path');
module.exports = {
context: path.join(__dirname, 'src'),
entry: './index.jsx',
output: {
path: path.join(__dirname, 'public'),
filename: './bundle.js'
},
module: {
loaders: [
{ test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ },
{ test: /\.jsx$/, loader: 'babel-loader', exclude: /node_modules/ },
],
},
resolve: {
modules: [
path.join(__dirname, 'node_modules')
]
}
};
The most common issue I found people were having with this error is that they put <script> in the head or before the <div>. Yet I don't do neither of these so I have no idea what the problem is.

I'm definitely a little late to the party here, but would like to post an answer for those who want to use webpack-dev-middleware instead of circumventing it.
The problem, for me, was that basic setup for webpack-dev-middleware is shown in the webpack docs using html-webpack-plugin with a default configuration. This plugin dynamically generates a new index.html file along with your bundle.js on save, so even though I wrote an index.html file that contained <div id="root"></div>, that wasn't the one that was being served to the browser. I was able to verify this by running /node_modules/.bin/webpack and watching the output in my public path directory.
My solution is as follows:
Add a configuration object to the declaration of the WebpackHtmlPlugin:
plugins: [
new HtmlWebpackPlugin({
title: "boilerplate",
template: path.join(__dirname, "pathto", "template.html"),
inject: "body",
}),
],
(This sets the title of the template file, its location, and directs html-webpack-pluginto push all script tags into the bottom of the body element of the generated file.) The template is as follows:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div id="root"></div>
</body>
</html>
More info can be found here:
https://webpack.js.org/plugins/html-webpack-plugin/
https://github.com/jantimon/html-webpack-plugin#options

Thanks to Axnyff for his help as it resolved my question. The problem was with a dependency I was using, webpack-dev-middleware.

Related

Element UI icons wont show up using Laravel Mix

I made a simple website using Vue and Element UI. I used Laravel Mix to compile my code.
During development, the icons are showing up but when I run "npm run prod" and upload it to Github Pages they wont show up.
This is my webpack.mix.js
let mix = require('laravel-mix');
mix.js('src/js/app.js', 'public/')
.sass('src/styles/app.scss', 'public/')
.babelConfig({})
.disableNotifications();
I am using on demand components and followed this doc so my root vue file looks like this:
import Vue from 'vue'
import store from './vuex'
import router from './vue-router'
import Element from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import lang from 'element-ui/lib/locale/lang/es'
import locale from 'element-ui/lib/locale'
locale.use(lang)
Vue.use(Loading.directive);
Vue.component(Select.name, Select)
Vue.component(Option.name, Option)
Vue.component(Input.name, Input)
Vue.component(Icon.name, Icon)
new Vue({
el: '#app',
router,
store,
});
Following the same doc, I added a .babelrc file on my root directory but I didn't managed to get it working with the preset es2015 so I used #babel/preset-env instead. I dont actually know how to properly use Babel so the whole error might be over here but idk.
{
"presets": [["#babel/preset-env", { "modules": false }]],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
I noticed something weird, when I run npm run prod, the output shows something like this:
The fonts folder and the needed fonts are being copied to my root directory, so when its on Github it makes a request to the root domain, the root folder, the right url should be over (I guess?) /h3lltronik.github.io/my-site/ but it is on /h3lltronik.github.io/.
Just in case is needed, Im using the icons like this:
<el-input v-model="search" prefix-icon="el-icon-search" class="filter_input element-input bordered" #input="onChangeSearch"
placeholder="Search for a country..."></el-input>
And this is my index.html
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>H3lltronik</title>
<link rel="stylesheet" href="./public/app.css">
</head>
<body>
<div id="app" :class="modeClass">
<transition name="el-fade-in">
<router-view class="content-body"></router-view>
</transition>
</div>
<script src="./public/app.js"></script>
</body>
</html>

Does order of imports in Webpack entry file matter

I'm having an issue where I have two components that I'm importing into my entry file "index.js" - depending on which I have as the first import, the second will not work and I get an error "Target Container is not a DOM Element." What am I missing? Why will the Proforma component only render if it's first in the index.js, and why does the App component try to load anyways when I browse to the page that the Proforma component loads (when it successfully loads and the console still has the above error)?
The index.js file looks like:
import App from "./components/App.js";
import Proforma from "./components/property_detail/proforma.js";
In that scenario, the page displaying App.js works - but still attempts to load Proforma despite that element not appearing anywhere in the App.js code. The same happens when I change the order of the elements and load the page that includes "proforma.js", which is just:
import React, { Component } from "react";
import ReactDOM from "react-dom";
class Proforma extends React.Component {
render() {
return (
<p>Proforma Page</p>
);
}
}
ReactDOM.render(
<Proforma />,
document.getElementById('proforma')
);
The template page that the Proforma component should be rendered on:
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{% static './css/bulma/bulma.css' %}">
<title>Test Proforma </title>
</head>
<body>
<section class="section">
<div class="container">
<div id="proforma"><!-- React --></div>
</div>
</section>
{% load static %}
<script src="{% static 'frontend/main.js' %}"></script>
</body>
</html>
For good measure, the package.json file and webpack.config look like:
I'm building the file with this:
package.json
{
"main": "index.js",
"scripts": {
"dev": "webpack --mode development
./simple_proforma_react/frontend/src/index.js --output
./simple_proforma_react/frontend/static/frontend/main.js",
....
}
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
}
};
Do you have a ReactDom.render in your proforma component file, as well as in your app.js/index.js file? That might cause a problem

Webpack inject js/css file content directly to index.html

I have code like this
<html>
<head>
<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet" type="text/css">
<link href="path_to_css/some_css.css" rel="stylesheet" type="text/css">
</head>
<body>
...
<script src="bootstrap/js/bootstrap.min.js"></script>
<script src="jquery/jquery.min.js"></script>
</body>
</html>
and I need plugin/loader or other way to get my html file with replaced link and script tags to content of this files, is there any way to do it?
Finnaly i wrote own plugin which fit my needs
include-file-webpack-plugin
It actually can be accomplish with:
npm i --save-dev css-loader to-string-loader
configure your webpack with
module: [
rules: [
{
test: /\.css$/,
use: ['to-string-loader', 'css-loader']
}
]
}
Then in your project you can access the css as string like so
const cssContent= require('path_to_css/some_css.css');
console.log('your css is: ', cssContent.toString());
Or maybe you want inject it manually to the page with:
const boostrap= require('bootstrap/dist/css/bootstrap.min.css');
let style= document.createElement('style');
style.id= 'boostrap';
style.setAttribute('type', 'text/css');
style.innerHTML= boostrap.toString();
document.body.appendChild(style);
Reference
Inject CSS stylesheet
css-loader

HtmlWebpackPlugin injects relative path files which breaks when loading non-root website paths

I am using webpack and the HtmlWebpackPlugin to inject bundled js and css into an html template file.
new HtmlWebpackPlugin({
template: 'client/index.tpl.html',
inject: 'body',
filename: 'index.html'
}),
And it produces the following html file.
<!doctype html>
<html lang="en">
<head>
...
<link href="main-295c5189923694ec44ac.min.css" rel="stylesheet">
</head>
<body>
<div id="app"></div>
<script src="main-295c5189923694ec44ac.min.js"></script>
</body>
</html>
This works fine when visiting the root of the app localhost:3000/, but fails when I try to visit the app from another URL, for example, localhost:3000/items/1 because the bundled files are not injected with an absolute path. When the html file is loaded, it will look for the js file inside the non-exist /items directory because react-router hasn't loaded yet.
How can I get HtmlWebpackPlugin to inject the files with an absolute path, so express will look for them at the root of my /dist directory and not at /dist/items/main-...min.js? Or maybe I can change my express server to work around the issue?
app.use(express.static(__dirname + '/../dist'));
app.get('*', function response(req, res) {
res.sendFile(path.join(__dirname, '../dist/index.html'));
});
Essentially, I just need to get the line:
<script src="main...js"></script>
to have a slash at the start of the source.
<script src="/main...js></script>
Try setting the publicPath in your webpack config:
output.publicPath = '/'
HtmlWebpackPlugin use the publicPath to prepend the urls of the injects.
Another option is to set the base href in the <head> of your html template, to specify the base url of all relative urls in your document.
<base href="http://localhost:3000/">
In fact, I had to put :
output.publicPath: './';
in order to have it working in a non-ROOT path.
At the same time I was injecting :
baseUrl: './'
into
<base href="<%= htmlWebpackPlugin.options.metadata.baseUrl %>">
With both parameter set, it worked like a charm.
in webpack config
config.output.publicPath = ''
in your index.html
<base href="/someurl/" />
this should do it.

jasmine 2.0, requirejs, testr - just a blank page with no errors

It seems that there are a number of posts grappling with Jasmine 1.3 and Requirejs, but I'm having trouble with 2.0. I am using Jasmine 2.0 for tests, requirejs for AMD compliance and testr to mock some of my modules in my tests.
When I open the page, however, it's blank with nothing in the console.
You can see the project in full at https://github.com/nopwd/client if that's more helpful.
I have a test.html page set up:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>NoPwd Testing Rig</title>
<link type="text/css" rel="stylesheet" href="lib/jasmine/lib/jasmine-core/jasmine.css" />
</head>
<body>
<script language="javascript" type="text/javascript" src="lib/requirejs/require.js"></script>
<script language="javascript" type="text/javascript" src="lib/testr.js/testr.js"></script>
<script language="javascript" type="text/javascript">
testr.config({
root: './',
baseUrl: './',
ignore: ['lodash']
});
testr.run('test.js', function() {});
</script>
</body>
</html>
I also have a test.js file which is the entry point:
require.config({
paths: {
// ...
},
shim: {
'jasmine/jasmine': {
exports: 'window.jasmineRequire'
},
'jasmine/jasmine-html': {
deps: ['jasmine/jasmine'],
exports: 'window.jasmineRequire'
},
'jasmine/boot': {
deps: ['jasmine/jasmine', 'jasmine/jasmine-html'],
exports: 'window.jasmineRequire'
},
'jasmine-ajax': {
deps: ['jasmine/jasmine', 'jasmine/boot'],
exports: 'window.jasmineRequire'
}
}
});
require(
[
'jasmine/jasmine-html', 'jasmine/boot', 'jasmine-ajax',
'spec/nopwd-spec', 'spec/hash-spec', 'spec/transport-spec'
],
function() {
'use strict';
}
);
I know for previous Jasmine versions you'd have to call jasmine.getEnv().execute() but it doesn't seem to be the case with 2.0.
Essentially, the problem is that jasmine attaches itself to window.onload(). Now since require() has been called, window.onload() is already used, and so the handlers never get called. The answer, I found, is to call window.onload() manually inside the entry point (for me: test.js).
There's a good example here.

Categories