Convert string React Component to jsx again - javascript

I have one question, because read javascript file from NodeJS and send to the client and here I reveive all file as string (which is obvious) and here is my question. Is any solution to convert string component again to the jsx? This is no only html tags so dangerouslySetInnerHTML or similar methods don't work.
My string components looks like typical React component, something like that:
import React from 'react';
import { Row } from 'react-bootstrap;
import Home from './Home'
......
const Index = () => {
const renderHelloWorld = <h1>Hello World</h1>
return (
<div>{renderHelloWorld}</div>
)
}
export default Index;
So this is string I'm struggling with how convert it to jsx (maybe this is impossible) and I should use Server Side Rendering with React methodfs like ReactDOMServer?

You can use just plain old JavaScript to do the trick.
document.querySelector('#elementToBeReplace').innerHTML = renderHelloWorld;
Another Option with react.js is use of dangerouslySetInnerHTML.
<div dangerouslySetInnerHTML={{ __html: renderHelloWorld }} />
Or You can use html-react-parser.
import Parser from 'html-react-parser';
const renderHelloWorld = <h1>Hello World</h1>
<div>{Parser(renderHelloWorld)}</div>

Try this library https://www.npmjs.com/package/react-html-parser.
A utility for converting HTML strings into React components. Avoids the use of dangerouslySetInnerHTML and converts standard HTML elements, attributes and inline styles into their React equivalents.

So, solution for my problem is very popular and simple (in early project stage), to understand problem and fix it we need to go back to the server part of the app. For React applications if we want render jsx file from the server, we have to use server side rendering and above problem will be gone. Maybe I show step by step how enable rendering React component in te server.
Configure backend to enable the ES6 features
Install babel packages
npm install #babel/core #babel/node #babel/preset-env #babel/preset-react --save-dev
There is many ways to configure Babel, I use the nearest package.json for this.
{
......,
/*This have to be in the top level in package.json*/
"babel":{
"presets":[
"#babel/preset-env",
"#babel/preset-react"
]
}
}
More information about babel packages and configurations: https://babeljs.io/docs/en/
Send React component to the client
For this we have to install react and react-dom packages in server side
npm install react react-dom
For example in your server,js or route.js file:
.... //necesarry imported modules
import ReactDOMServer from 'react-dom/server'
import Index from './Index';
router.get('/exampleRoute', (req, res) => {
.... //your route business logic
res.send(ReactDOMServer.renderToString(<Index/>))
})
Render view in the client
...//correct React component
const[state, setState] = useState({Component: ''});
fetch('/exampleRoute')
.then(response => response.json())
.then(data => setState(state => ({...state, Component: data.data));
....
return(
<div dangerouslySetInnerHTML={{ __html: state.Component }}></div>
)
This is only simple example how you can render React component from backend if this is necasarry. This is not guide for complex server side rendering in application which is more complicated thing, but no difficult thing.

Related

How to use scss modules in Next.js server components

I am trying to implement server components in my Next.js app. I'm using scss modules for styling.
A typical component in my project looks like this:
//MyComponent.client.jsx
import s from './MyComponent.module.scss';
export const MyComponent = ({ props }) => {
return <div id={ s.wrapper }>{ props.stuff }</div>
};
When I change this to: MyComponent.server.jsx
Styling ceases to work, and I don't get any errors.
How can I maintain this functionality in a server component?

How to use React components as part of legacy HTML/JS app?

I have an old web application running with HTML/JS.
I have created a new react application and my goal is to start developing new features / pages using React, and implement them in the current application.
The main goal is to use React components outside react, for example:
<html>
<head>
<title> My old web applciation</title>
// Imports for my react app / components
</head>
<body>
<!-- Old staff -->
<Footer someProp="1"/>
</body>
</html>
What I have so far:
For full-page features I used Iframe (and created a route in React for it)
Using element ID, e.g::
and in react:
const GiveItem = ({ ...props }) => {
console.log("init give item component");
return (
<section>
Give Item
</section>
);
};
try {
const domContainer = document.querySelector('#giveItem');
render(e(GiveItem), domContainer);
} catch (e) {
console.error('Failed to render give item', e);
}
export default GiveItem;
Is there any legitimate way to "export" react components to HTML (outside react) and use them as native components like:
<GiveItem someProp="1"/>
Using Vue I managed to do it, just by wrapping the highest-level element with:
<div id="vapp">
.... My old code
<VueComponent />
So back to the question - How I can show/use React components in different parts of legacy app as native HTML components?
Thanks!
I will divide my answer into 3 parts:
simple inclusion of react in general
make your example work
modules
(I will use yarn below. You can use npm as well, I assume you are familiar with these.)
1. simple inclusion of react in general
See Add React to a Website.
index.html:
<html><head>
<title>My old web applciation</title>
</head><body>
<h1>old stuff</h1>
<p>Some old HTML content.</p>
<!-- add a container, where you want to include react components -->
<div id="injected-react-content"></div>
<!-- import the react libraray -->
<script src="https://unpkg.com/react#16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.development.js" crossorigin></script>
<!-- import your react component -->
<script src="GiveItem.js"></script>
</body></html>
GiveItem.js:
(modified from JSX to JS. For JSX see section 2.)
const GiveItem = (props) => {
console.log("init give item component");
return React.createElement(
"section",
null,
"Give item content"
);
};
const domContainer = document.querySelector('#injected-react-content');
ReactDOM.render( React.createElement(GiveItem), domContainer );
2. make your example work
Your component uses JSX. You need to transpile it to JS, using babel.
GiveItem.jsx:
(it is not necessary to call it .jsx, but it makes sense)
const GiveItem = (props) => {
return (
<section>
Give Item
</section>
);
};
const domContainer = document.querySelector('#injected-react-content');
ReactDOM.render( React.createElement(GiveItem), domContainer );
Install babel:
yarn add #babel/cli #babel/core #babel/plugin-transform-react-jsx #babel/preset-react --dev
Transpile your JSX file ./src/GiveItem.jsx into a JS file in ./dist/GiveItem.js:
yarn babel ./src/GiveItem.jsx --presets=#babel/preset-react --out-dir dist
(the dist folder will be created if it doesn't exist)
If you now copy the index.html into ./dist,
you should have the same code as in section 1.,
and opening ./dist/index.html in the browser should work.
3. modules
Of course, you would want to import other react components and sub-components.
(And you probably don't want to import everything individually with <script> tags.)
if an environment is set up already
Maybe your old app already runs in a yarn (or npm) environment, then you might be fine with
install yarn add react and yarn add react-dom
removing the two <script src="https://unpkg.com/react... lines (as react is probably already imported inside your components),
then import some root component (instead of GiveItem.js before),
where you do the ReactDOM.render(...) and import further modules:
E.g.:
index.html:
<!-- import your react component -->
<script type="module" src="EntryIntoReactWorld.js"></script>
EntryIntoReactWorld.js:
import SomeComponent from './SomeComponent';
import SomeOtherComponent from './SomeOtherComponent';
const ReactRoot = props => {
return React.createElement(
"div",
null,
React.createElement(SomeComponent, null),
React.createElement(SomeOtherComponent, null)
);
};
ReactDOM.render(
React.createElement(ReactRoot),
document.querySelector('#injected-react-content')
);
if environment is not set up already
If your old app is not already running in a yarn (or npm) environment, you have to set one up.
Unfortunately, this is not trivial.
(I tried to write a short working minimal example here, but I failed.)
For that you have to enter the world of Javascript modules.
But modern browsers don't allow many things from the local file system.
(e.g. see CORS problems, MIME problem, ...)
You have to install a server for development. You might start with e.g. http-server, but there you probably still will have problems, so I suggest to already start with writing a server.js file and use node http.
(Maybe expressjs as well. It is not necessary, but everybody uses it, and it is easier to find help and tutorials.)
You also might need webpack.
Of course you also have to install yarn add react and yarn add react-dom.

How to use HTML with JS in React app to export component

I am building MERN project and in react part I got:
- src/
- components/
- AdminPage/
- admin-page.html
- admin-page.css
- admin-page.js
So the problem is in App.js:How could I use regular html, css, js and not ``react in <AdminPage/> component:
import React from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import HomePage from './components/HomePage/HomePage.component';
import LoginPage from '../src/components/LoginPage/LoginPage.component';
import RegisterPage from '../src/components/RegisterPage/RegisterPage.component';
import UserPage from '../src/components/UserPage/UserPage.component';
import AdminPage from '../src/components/AdminPage/AdminPage.component';
Is there way NOT to use the classic way like
AdminPage.component.jsx and from there export the component; how could I do that with regular html, css and js?
I'm assuming you don't want to consider a functional component because of maintaining something in the html/css/js that can't be easily refactored into React:
ie.
const NewComponent = () => {
const functions = () => {
}
return (
<div style={styles} ></div>
);
}
const styles = {
...css
}
export default NewComponent;
Then I'd say your best solution would be to paste the body of html from admin-page.html into you index.html file.
Preferably under the root div tag ( ).
This will show up under all your React code (like a footer would) but you can use a class name or id to show / hide the page under certain conditions.
Then just link your css and js as separate stylesheets / scripts in the header and footer.
I would strongly advise against this though as it will most likely increase your technical debt to the project.
Hope it helps : )
[update]
By default, React does not permit you to inject HTML in a component, for various reasons including cross-site scripting. However, for some cases like a CMS or WYSIWYG editor, you have to deal with raw HTML. In this guide, you will learn how you can embed raw HTML inside a component.
dangerouslySetInnerHTML Prop
If you try to render an HTML string inside a component directly, React will automatically sanitize it and render it as a plain string.
Ok so looking at this again if you just want to add the complete 200+ lines of HTML / JS I'd say you could just import them to a component with the dangerously SetHTML prop. Like so:
const HTML = import('../the/file/path/to/the.html');
const JS = import('../the/file/path/to/the.js');
const newComponent = () => {
return (
`<div dangerouslySetInnerHTML={{ __html: myHTML }} />;`
)
}
Alternatively, If you want a safer solution you could use dompurify:
If XSS is a primary concern, you can use an external library like DOMPurify to sanitize the HTML string before injecting it into the DOM using the dangerouslySetInnerHTML prop.
To install the DOMPurify library, run the following command.
npm i dompurify
You can see the example usage below.
import DOMPurify from "dompurify";
const myHTML = `<h1>John Doe</h1>`;
const mySafeHTML = DOMPurify.sanitize(myHTML);
const App = () => <div dangerouslySetInnerHTML={{ __html: mySafeHTML }} />;
You can also configure DOMPurify to allow only specific tags and attributes.
// ...
const mySafeHTML = DOMPurify.sanitize(myHTML, {
ALLOWED_TAGS: ["h1", "p", "span"],
ALLOWED_ATTR: ["style"],
});
// ...
With many thanks to Gaurav Singhal for this brilliant article:
https://www.pluralsight.com/guides/how-to-use-static-html-with-react

How to load a React.Component from a CDN and render into another React.Component

Note: None of the answers actually work [DO NOT DELETE THIS NOTE]
simple question, I got a project,
npx create-react-app react-project (consider this Project Y)
now, inside this project's App.js
import React, { Component } from 'react'
export default class App extends Component {
render() {
return (
<div>
HELLO
</div>
)
}
}
now in CDN I have another Comp.js (Consider this Project X)
https://codepen.io/sirakc/pen/ZEWEMjQ.js
import React, { Component } from 'react'
export default class Comp extends Component {
render() {
return (
<div>
WORLD
</div>
)
}
}
now I want to show the Comp.js into App.js as if you are taking it from local source folder
so
import React, { Component } from 'react'
//somehow somewhere import Comp.js and then <Comp/>
export default class Comp extends Component {
render() {
return (
<div>
HELLO <Comp/>
</div>
)
}
}
and ofc the output should be
HELLO WORLD
when I run the project react-project and if in the CDN I change WORLD to EARTH it should change WORLD to EARTH in the output as well
so now react-project's output is HELLO EARTH
I am putting all my rep into a bounty for this, upvote if you like this question to help me attract attention.
NOTE: my need is to show React project X inside React project Y without touching much of project Y and ofc update the project X without updating anything inside project Y, so yea the <script src='chunk.js'/> isn't gonna work here, the chunk name changes, if you can find a way to not make it change, then its great, do share. If you know a working way to do this bundled into chunk.js DO SHARE!
ANY WAY OF DOING THIS IS WELCOMED, as long as Project X is independent of Project Y and I can make changes to Project X without changing Project Y
There are a few options you have at hand.
Option 1 - Create a NPM Package
Turn Project X into a module.
This will mean you will go to Project X development folder, and run npm login and npm publish. You can read more about that here
After that, once your package is on NPM You can go to Project Y and do the following:
import React, { Component } from 'react'
import Comp from 'my-package'
export default class Comp extends Component {
render() {
return (
<div>
HELLO <Comp/>
</div>
)
}
}
Option 2 - Load a bundled JS
Instead of having your script load the following:
import React, { Component } from 'react'
export default class Comp extends Component {
render() {
return (
<div>
WORLD
</div>
)
}
}
This is JSX Syntax. And it cannot be read in plain Vanilla JS - thus you cannot just import it like <script src="myscript.js" /> since this is not valid JS without a parser like Babel.
I would go to Project X and run npm run build. After that I would get the bundle.js - bundled and minified script written in Plain JS. It would look something like this:
(this.webpackJsonpchrome_extension=this.webpackJsonpchrome_extension||[]).push([[2],[function(e,t,n){"use strict";e.exports=n(99)},,function(e,t,n){"use strict";function r(){return(r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}n.d(t,"a",(function(){return r}))},function(e,t,n){"use strict";function r(e,t){if(null==e)return{};var n,r,i={},o=Object.keys(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)
Basically non-human readable code, which is parsable by <script src="myscript.js" /> tag. And then you would have to go to your index.html and inject it there, or use some of modules like react-script-tag
I would highly highly recommend going with Option #1. Since this is the preferred way to go. Look into creating NPM packages from your React project, and follow step by step.
Some more useful links about Option #1:
Create a simple React npm package in simple steps using CRA
How to publish your React component on npm
Hope this will guide you in the right direction, but the current way you are doing it is a no-go
EDIT - Tehnically there is an option #3, but I wouldn't recommend it.
Option 3 - Make your url provide just JSX, and load it in dangerouslySetInnerHtml.
Let's say your https://codepen.io/sirakc/pen/ZEWEMjQ.js would provide with this only:
<div>
WORLD
</div>
Technically, you could then turn your link into something more readable, like .txt extension, fetch it, store it in a variable, and load it in dangerouslySetInnerHTML.
for example:
const otherProjectJSX = somehowLoad(https://codepen.io/sirakc/pen/ZEWEMjQ.js)
const MyApp = () => <div dangrouslySetInnerHtml={otherProjectJSX} />
Basically it would be this:
const otherProjectJSX = '<div>WORLD</div>'
const MyApp = () => <div dangrouslySetInnerHtml={otherProjectJSX} />
I would not recommend this, but if it is only what is inside render() you care about - it might work after all.

using npm package in react app

I have some ad-hoc javascript knowledge and am trying to learn react, but can't seem to locate documentation on how to use imports correctly. Specifically, I have a quick app that fetches a value from an api I set up, and I would like to format the number using katex. There is a react-katex package I installed using npm, but the instructions don't seem to cover how to accomplish this using webpack/jsx/whatever.
More specifically, how would I use the package? The documentation says to use it thus
var BlockMath = ReactKaTeX.BlockMath;
ReactDOM.render(<BlockMath math="\\int_0^\\infty x^2 dx"/>, document.getElementById('katex-element'));
but when I do this in the example code below I get an error that the element katex-element is undefined. I realize (I think) that the first line is replaced by the import command, so I know I don't need that, but where do I put the BlockMath call to get it to render the number in tex?
Here is my example app, I've tried a few things, but I either end up getting undefined errors, or no result at all:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
// ?? import 'react-katex';
class App extends Component {
constructor(props) {
super(props)
this.state = {
number: 0
}
}
componentDidMount() {
fetch('http://localhost:4001/api/get_number')
.then(data => data.json())
.then(data => {
this.setState({
number: data.number
})
})
}
render() {
const number = this.state.number
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
Also <span id="katexElement">{number}</span>
</p>
</div>
);
}
}
export default App;
I think there is a similar question here: Is there a different between using an npm package in Node.js vs using it in React / webpack?
you can import it using
import {InlineMath, BlockMath} from 'react-katex'
Notice the curly braces {}, it will get only specified property from the library and not the whole library.
and can use these component directly in your jsx, like:
const inlineMath = (
<div>
<InlineMath math="\\int_0^\\infty x^2 dx"/>
</div>
);
Notice: Please dont forget to add css.
Don't forget to import KaTeX CSS file (see example/index.html).
Use this inside your index.html to import css in your code.
<link rel="stylesheet" href="../node_modules/katex/dist/katex.min.css">
I would suggest you to use {} braces to get only the specific property from the library rather than loading the whole library at once. Also it makes the code much more clearer and readable.
Using import {InlineMath, BlockMath} from 'react-katex' would let you leverage InlineMath.function().
Alternatively, you should just be able to include
import ReactKatex from react-katex
which would then allow you to access the entire library via ReactKatex.subexport.function where subexport is a nested module (such as InlineMath from the example above) and function is a defined function within that submodule.

Categories

Resources