Why cannot render HTML with ReactJS - node.js

I have seen online plenty of examples and tests using React and typescript where they issue something like this:
import * as ReactDOM from 'react-dom';
ReactDOM.render(
<h1>Hello world!!</h1>, //or any other valid html snippet
document.getElementById('root') as HTMLElement
);
However, when I try to reproduce those multiple examples in my machine, I get, first a highlight error from VS code, and then when I try to bundle I get this error:
TS2686: 'React' refers to a UMD global, but the current file is a
module. Consider adding an import instead.
If instead of putting the HTML as argument of the function I write a my SimpleComponent.render(), the bundle will be produced without errors.
What is wrong with that code snippet?

Try to add import * as React from 'react'. <h1> is React component (React.createClass('h1') after transpile JSX to JavaScript), but you have imported only ReactDOM.

Related

Can you instantiate another `BrowserRouter` inside a `BrowserRouter` based App?

Background: I am trying to use sweetalert2-react-content to let me put a react <Link> inside a Sweetalert2 footer.
Generally speaking sweetalert2-react-content is supposed to let you place react JSX into its fields, like this:
MySwal.fire({
text: "Fire fire",
footer: <div>Call the firebrigade</div>
});
... and indeed that sort of thing does work.
However, putting a <Link> there does not work: it renders empty.
In this issue resolution message the the advice is "wrap your element in BrowserRouter like this:
MySwal.fire({
html: (
<BrowserRouter>
...
</BrowserRouter>
),
})
Is this "legitimate"? What does it "mean" to have a BrowserRouter inside an app that is routed using BrowserRouter already?
No, it is an invariant violation to nest a router within another router. I think your situation is not a case of invalid nesting, but more to do with where sweetalert is rendering the React JSX. From what I recall of sweetalert it renders content outside the ReactTree.
You can certainly render more than one router, so long as they are not nested, but then the issue is that you've separate routing contexts that each individually handle routing/navigation, and navigating within one routing context doesn't update the others.
I suspect you could use a single custom history reference and pass these to the routers you need, so they all reference the same history context internally.
react-router-dom#6 exports a HistoryRouter for this purpose.
Example:
import { createBrowserHistory } from "history";
const history = createBrowserHistory({ window });
export default history;
...
import * as React from "react";
import * as ReactDOM from "react-dom";
import { unstable_HistoryRouter as HistoryRouter } from "react-router-dom";
import history from "../path/to/history";
ReactDOM.render(
<HistoryRouter history={history}>
{/* The rest of your app goes here */}
</HistoryRouter>,
root
);
...
import { unstable_HistoryRouter as HistoryRouter } from "react-router-dom";
import history from "../path/to/history";
MySwal.fire({
html: (
<HistoryRouter history={history}>
...
</HistoryRouter>
),
})
Note about unstable_HistoryRouter:
This API is currently prefixed as unstable_ because you may
unintentionally add two versions of the history library to your app,
the one you have added to your package.json and whatever version React
Router uses internally. If it is allowed by your tooling, it's
recommended to not add history as a direct dependency and instead rely
on the nested dependency from the react-router package. Once we have a
mechanism to detect mis-matched versions, this API will remove its
unstable_ prefix.
No, this is wrong and will usually throw an error.
What you would like to do is to render it like this:
<UNSAFE_LocationContext.Provider value={null as any}>
<BrowserRouter>
...
</BrowserRouter>
</UNSAFE_LocationContext.Provider>

Cant import CSS from MDCTextField to style MDCTextField child elements in LitElement based WebComponent

How do you import CSS into a ES6 module?
I receive the following error in browser console;
Failed to load module script: The server responded with a
non-JavaScript MIME type of "text/css". Strict MIME type checking is
enforced for module scripts per HTML spec.
Module below:
import { LitElement, html, css } from "lit-element";
import { MDCTextField } from "#material/textfield";
import style from "#material/textfield/dist/mdc.textfield.css";
export class MyWC extends LitElement {
static get styles() { return style; } //was using return css'...'
render() {
return html`
<label class="mdc-text-field mdc-text-field--textarea">
<textarea class="mdc-text-field__input" aria-labelledby="my-label-id" rows="8" cols="40" maxlength="140"></textarea>
...blah blah blah...
</label>
`;
}
#material/textfield & lit-element installed via npm OK. I'm using es-dev-server on linux.
ps - I want to use MDC web components but keep things as simple as possible.
Any help appreciated - Thanks.
The HTML spec currently only allows to import javascript modules. This is enforced by checking that the MIME type of the imported file is a javascript one, hence the error you're getting. The fact that in some environments (especially with bundlers/transpilers) importing other resource types is possible may give the wrong impression that it is case also in the browser.
To use this kind of import
import style from "#material/textfield/dist/mdc.textfield.css";
you would need some tool capable of transforming it into a CSSResult. A typical scenario is using bundlers like Rollup or Webpack with dedicated plugins/loaders (ie rollup-plugin-lit-css or lit-css-loader).

Chrome Extensions import CSS framework will make effect to the loaded page

I tried to use the content scripts to make an popup page by Vue.js and Bootstrap the popup page works good, but the side effect of this let the original website components setting become a chaos. I used es6 and compile by webpack.
As following my code:
import Vue from 'vue';
import BootstrapVue from 'bootstrap-vue';
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap-vue/dist/bootstrap-vue.css';
import 'animate.css/animate.min.css';
//component
import App from './App.vue';
//scripts
Vue.use(BootstrapVue)
Vue.config.silent = true;
var initDom = document.createElement("div");
initDom.id = "extensionUIwrap";
document.getElementsByTagName("body")[0].appendChild(initDom);
new Vue({
render: h => h(App)
}).$mount('#extensionUIwrap')
How to let the css module just made effect on my popup page or exclude effect from the original website?
Try using Vue inside shadow dom, like explained in this answer.
It will completely isolate your extension's DOM from pages.

import * best practice in node and react

Should I be importing my node modules using *
example
import * from 'express';
import * from './../../myCode';
Is it correct that by using the * that all exports will be imported which will make me bring functionality which will increase the file size.
import * as myCode from './../../myCode';
This inserts myCode into the current scope, containing all the exports from the module in the file located in ./../../myCode.
import React, { Component } from 'react';
class myComponent extends Component { ... }
By Using above syntax your bundler ( e.g : webpack) will still bundle the ENTIRE dependency but since the Component module is imported in such a way using { } into the namespace, we can just reference it with Componentinstead of React.Component.
For more information you can read mozilla ES6 module docs.
The answer is, it depends: there is no best practice for import/export since it's very up to you and your use-case. But normally I will just import what I need, not everything. And yes, if you do import * the file size of bundle.js can be big.

What makes a typescript module, a typescript module? Toastr example

I was just using toastrjs for a few notifications, and I ran into this little problem. Ideally, when you import a library in nodejs, you have to make an import statement, like so:
import http = require("http");
However, when I tried this with toastr, I get an error, even after including the reference path. So, something like this:
///<reference path='toastr.d.ts' />
import toastr = require("./toastr");
I get this error:
error TS2071: Unable to resolve external module '"./toastr.js"'.
error TS2072: Module cannot be aliased to a non-module type.
How is toastr different from a regular node module like http?
Update 1
I tried to do the same thing with jQuery but I have the same problems, does this mean that this does not work with frameworks that are designed to be client-side?
the following declare definition would create a module you can import via amd/commonjs:
declare module "jquery"{
export var jQuery: JQueryStatic;
}
Then you can do:
import jquery = require("jquery");
You can see such definitions in this underscore definition: https://github.com/borisyankov/DefinitelyTyped/blob/master/underscore/underscore.d.ts#L2853
or node.d.ts : https://github.com/borisyankov/DefinitelyTyped/blob/master/node/node.d.ts#L203
However not all files on DT have this definition. As it is simple enough to add on your own and you are free to name these modules whatever you want (in your AMD configuration http://www.youtube.com/watch?v=4AGQpv0MKsA )

Resources