React: How to inject React component into body? - javascript

I have a React component that I want to inject into the DOM. This is because my JS will be loaded through a script tag by other website owners, not loaded onto a SPA under my control.
What I want to do is append my Root component into the body of the webpage.
If I do something like this, then it replaces all the contents of my body, which is not what I want.
import React from "react";
import ReactDOM from "react-dom";
class Root extends React.Component {
render() {
return <div>heyyyyyyy</div>;
}
}
if (!module.parent) {
ReactDOM.render(<Root />, document.querySelector("body")); // <-- wrong
}
I want something like document.querySelector("body").appendChild(<Root />). Is this possible?

If you opt for a one-liner :
ReactDOM.render(
<Root />,
document.body.appendChild(document.createElement("DIV"))
)
Running Example:
class Root extends React.Component {
render() {
return <div>It works!</div>;
}
}
ReactDOM.render(
<Root />,
document.body.appendChild(document.createElement("DIV"))
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.0.0/umd/react-dom.production.min.js"></script>
<body></body>

Create the root element and append it to the DOM yourself
const rootEl = document.createElement('div')
document.body.appendChild(rootEl)
class Root extends React.Component {
render () {
return <div>heyyyyyyy</div>
}
}
ReactDOM.render(
<Root />,
rootEl
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div>don't replace me</div>

I put my extended and complex answer cause it may help if you need to import one/multiple react components without npm in server side render:
You may go without NPM/Webpack but you gotta use babel:
In my case it is server side rendering, that's why i cannot use npm
First: import all dependencies and put your main module like this to html :
<script type="module" src="/jsx/mainPage.js"></script>
//specify js, not jsx because babel compiles jsx files to js
<script>
new mainPage({
containerID: "${parentID}"
})
</script>
<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>
//since babel-watched is used, you dont need babel cdn lib anymore
Second: write your jsx in the next way
//my MainPage.jsx
{ ChildPageComponent } from './childPage.js';
window.MainPage = function(props) {
ReactDOM.render(<MainPageComponent constainerID={props.containerID}/>,
document.getElementById(props.containerID));
}
class MainPageComponent extends React.Component {
render() {
return <ChildPageComponent/>
}
... }
my child page.jsx
export class ChildPageComponent extends React.Component {
render(){
return(<div>helloword</div>)
}
}
But the most helpful is Babel watcher. This bash script helps to install and run babel-watcher. You gotta specify your pathes for source and compiled project files
#!/bin/bash
if [ ! -d "node_modules" ]; then
npm init -y
npm install babel-cli#6 babel-preset-react-app#3
fi
SOURCES=~/Documents/yourpath/project/jsx
OUT=~/Documents/yourpath/project/jsx
npx babel --watch $SOURCES --out-dir $OUT --presets react-app/prod
Sure it help you because i was looking for this way for a long

Related

how to convert html script tag to react code?

I am a freshman of javascript and react. My question is: How to convert the following code to react code?
<div id="SOHUCS" sid="xxx"></div>
<script charset="utf-8" type="text/javascript" src="https://cy-cdn.kuaizhan.com/upload/changyan.js" ></script>
<script type="text/javascript">
window.changyan.api.config({
appid: 'xxx',
conf: 'xxxxx'
});
</script>
Using componentDidMount()
import React, {Component} from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends Component {
componentDidMount() {
const script = document.createElement("script");
script.async = true;
script.src = "https://some-scripturl.js";
this.div.appendChild(script);
}
render() {
return ( <
div className = "App"
ref = {
el => (this.div = el)
} > < h1 > Hello react < /h1> {
/* Script is inserted here */ } <
/div>
);
}
}
export default App;
Using react-helmet
React helmet is an npm library that manages browser head manager, It is very easy to change web page lines of code inside a head tag.
First, install react-helmet with the npm install command
npm install react-helmet
It adds the dependency to package.json
"dependencies": {
"react-helmet": "^6.1.0",
}
Complete component code to add a script tag to component using react-helmet.
import React, { Component } from 'react';
import { Helmet } from 'react-helmet';
class AddingScriptExample extends Component {
render() {
return (
<div className="application">
<Helmet>
<script src="https://use.typekit.net/hello.js" type="text/javascript" />
</Helmet>
...
</div>
);
}
}
export default AddingScriptExample;

Why a ts-class-based vue-component's static method, which is declared in .vue, can only work in a .vue's script block?

Why a ts-class-based vue-component's static method, which is declared in .vue, can only work in a .vue's script block?
steps to reproduce
use vue-cli3 to init a typescript project and add shims-vue.d.ts
declare module "*.vue" {
import Vue from "vue";
export default Vue;
}
add Comp.vue file in your project as below
// Comp.vue
<template>
<div></div>
</template>
<script lang="ts">
import { Component, Vue, Prop } from "vue-property-decorator";
#Component
export default class Comp extends Vue {
mounted() {
}
created(){
}
static notWorkFunc(){
//anything
}
}
export function anotherNotWorkFunc(){
//anything
}
</script>
add test.ts and test.vue in your project with specific code as below
test.vue
<script lang="ts">
import ComP,{anotherNotWorkFun} from "./Comp.vue";
ComP.notWorkFunc()
anotherNotWorkFun()
</script>
test.ts
import ComP,{anotherNotWorkFun} from "./Comp.vue";
ComP.notWorkFunc()
anotherNotWorkFun()
As you can see
in .ts not work
in .vue work
I don't know the reason...
The repo is https://github.com/WilkinWendy/vue-ts-problem.
The democode is in ./src/demo
FYI
I think the typescript class components in .vue files actually get compiled to a Vue options object and that is how they are exported.
What we do in our project, is in the .vue file we just have the template and at the bottom we have external reference to a code-behind file.
Example:
<!-- Comp.vue -->
<template>
<div></div>
</template>
<script lang="ts" src="./Comp.ts"></script>
<style lang="scss" src="./Comp.scss"></style>
Then we do the following:
// Comp.ts
import { Component } from "vue-property-decorator";
export const SOME_CONST = "SomeValue";
#Component
export class Comp extends Vue{
public static method(): boolean {
return true;
}
}
export default Comp;
this seems to work for us and actually the performance of VSCode/Vetur/TypeScript is much better this way. In addition, when the UX folks work on the CSS/HTML they don't have to touch the .ts file.

React importing material-ui components not working

I'm new to React. I have a local development server (node http-server) and have installed material-ui package.
According to the material-ui docs, to add a component, I simply import it like any other module:
import Button from '#material-ui/core/Button';
However, when I try this, my webserver is returning a 404 and Firefox console outputs this: Loading module from “http://localhost:8080/node_modules/#material-ui/core/Button/” was blocked because of a disallowed MIME type (“text/html”)
The directory is accessible because I can reference the ./node_modules/#material-ui/core/Button/Button.js file and it is returned by http-server. But if I import that file, I get
SyntaxError: import not found: default.
I've tried importing index.js from that directory, but get same error.
How do I import the Button component (as shown in the material-ui example) correctly?
Here is my code (being served by http-server on localhost:8080)
(I am using npx babel to compile the JSX to js before serving)
test.html:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Test React</title>
<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>
</head>
<body>
<div id="app"></div>
<!-- React scripts -->
<script type="module" src="./test.js"></script>
</body>
</html>
test.js:
import { Mod1 } from './module1.js';
export class TestComponent extends React.Component
{
render()
{
return <h1>Hello world!</h1>;
}
}
export const TestC2 = () =>
{
return <h2>This is a h2</h2>;
}
ReactDOM.render(<div><TestComponent /><TestC2 /><Mod1 /></div>, document.getElementById('app'));
module1.js
// module1
import Button from './node_modules/#material-ui/core/Button';
export class Mod1 extends React.Component
{
constructor(props)
{
super(props);
this.state = {};
}
componentWillMount(props)
{
console.log("willMount", props);
}
componentDidMount(pp, ps)
{
console.log("didMount", pp, ps);
}
render()
{
console.log('render', this.props, this.state);
return <Button />;
}
}

strange error cannot resolve <folder name> in javascript

I have below code structure,
and my src/components/App.js look like this
import React, { Component } from 'react'
import { max_number } from '../helper'
class App extends Component {
render() {
return (
<div>
</div>
)
}
}
export default App
As you can see helper folder is the same level as components, but somehow I got error of Module not found: Can't resolve '../helper' in '/Users/james/Documents/react-demo/src/components'
helper.js is a directory you need to import from '../helper.js'
preferably rename the folder to helper

How integrate jQuery plugin in React

I want to use https://github.com/t1m0n/air-datepicker with in a React app, but it doesn't work.
import React from 'react';
import AirDatepicker from 'air-datepicker';
class Datepicker extends React.Component {
render() {
return(
<AirDatepicker />
)
}
}
export default Datepicker;
`
<script src="./../bower_components/jquery/dist/jquery.min.js"></script>
This produces:
error($ is not defined)
Another approach:
import React from 'react';
import $ from 'jquery';
import AirDatepicker from 'air-datepicker';
class Datepicker extends React.Component {
render() {
return(
<AirDatepicker />
)
}
}
export default Datepicker;
Same error.
How can I integrate a jQuery plugin with React?
First of all air-datepicker is not React component, it's jQuery plugin, so it won't work like in your examples.
Secondly, for proper work, jQuery should be availabel in global context, the most esiest ways to do this is to include it into page via <script> tag. It should be included before plugin script.
To check if its really included and it available globally, just type in Chrome console window.jQueryand press Enter it should return something like function (a,b){...}. If not, when you doing something wrong, check src attribute of <script> tag, maybe it pointing to wrong destination
How to get it worked in React?
Well, the most simpliest way is just to initialize plugin on any DOM element in your component, like in regular JavaScript.
class MyComponent extends React.Component {
componentDidMount(){
this.initDatepicker();
}
initDatepicker(){
$(this.refs.datepicker).datepicker();
}
render(){
return (
<div>
<h3>Choose date!</h3>
<input type='text' ref='datepicker' />
</div>
)
}
}
ReactDOM.render(
<MyComponent />,
document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/air-datepicker/2.2.3/js/datepicker.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/air-datepicker/2.2.3/css/datepicker.min.css" rel="stylesheet"/>
<div id="app"></div>
As separate component
Very simple datepicker React component example
class Datepicker extends React.Component {
componentDidMount(){
this.initDatepicker();
}
initDatepicker(){
$(this.refs.datepicker).datepicker(this.props);
}
render(){
return (
<input type='text' ref='datepicker'/>
)
}
}
class MyComponent extends React.Component {
render(){
return (
<div>
<h3>Choose date from React Datepicker!</h3>
<Datepicker range={true} />
</div>
)
}
}
ReactDOM.render(
<MyComponent />,
document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/air-datepicker/2.2.3/js/datepicker.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/air-datepicker/2.2.3/css/datepicker.min.css" rel="stylesheet"/>
<div id="app"></div>
Also don't forget to include css files.
air-datepicker is not the React-component. It is the jquery-plugin, so we can follow this tutorial https://reactjs.org/docs/integrating-with-other-libraries.html
import React from 'react'
import $ from 'jquery'
import 'air-datepicker/dist/js/datepicker.js'
import 'air-datepicker/dist/css/datepicker.css'
class AirDatepicker extends React.Component {
componentDidMount(){
this.$el = $(this.el)
this.$el.datepicker()
}
render() {
return (
<div>
<input ref={el => this.el = el}/>
</div>
)
}
}
export default AirDatepicker
But it still not work cause the jquery not the dependency of the air-datepicker.
ReferenceError: jQuery is not defined
./node_modules/air-datepicker/dist/js/datepicker.js
D:/demo/react/jq-plugin/datepicker/node_modules/air-datepicker/dist/js/datepicker.js:2236
2233 | }
2234 | };
2235 | })();
> 2236 | })(window, jQuery);
2237 |
2238 |
2239 | //////////////////
Follow the error message and the easiest way is to hake the air-datepicker. Add jQuery as the dependency in the first line of the air-datepicker/dist/js/datepicker.js
Before:
1 |;(function (window, $, undefined) { ;(function () {
2 | var VERSION = '2.2.3',
3 | pluginName = 'datepicker'
After:
> 1 |import jQuery from 'jquery'
2 |;(function (window, $, undefined) { ;(function () {
3 | var VERSION = '2.2.3',
4 | pluginName = 'datepicker'
Thus <AirDatepicker /> can works well as the React-component.
My Solution is
import 'stupid-table-plugin';
...
async componentDidMount() {
window.$("table").stupidtable()
}

Categories

Resources