Using static html/css/jquery landing pages in ReactJS project - javascript

so I had an idea of generating various "landing pages" for my project that would use similar elements with different data.
The idea is to essentially to have my react app (create-react-app) load a "container component" and would then display static landing pages.
For example files are...
screenContainer.jsx
pageOne.html
pageTwo.html
Depending on the user's choice I can render pageOne.html or page2.html. These pages are "templates" which work with jquery css, etc.
Is this possible? If so, what is the best approach.
I'm using html-loader now but am stuck at this:
./src/landingPages/serre/assets/js/plugins/jquery/jquery-3.3.1.min.js
Line 2:1: Expected an assignment or function call and instead saw an expression no-unused-expressions
Any ideas?
Thanks!
Here is my current file react screen container component:
require("es6-object-assign/auto");
import React, { Component, Fragment } from "react";
import $ from "jquery";
import Page from "../landingPages/serre/index.html";
var ReactDOMServer = require("react-dom/server");
var HtmlToReactParser = require("html-to-react").Parser;
var htmlDoc = { __html: Page };
class CreatorLandingPageContainer extends Component {
constructor(props) {
super(props);
}
render() {
return <Fragment>HELLO{this.renderPage()}</Fragment>;
}
renderPage() {
var htmlToReactParser = new HtmlToReactParser();
var reactElement = htmlToReactParser.parse(htmlDoc);
return reactElement;
}
}
export default CreatorLandingPageContainer;

Related

Designing persistent layouts in Next.js

I'm going through this article and I'm trying to figure out how the persistence is supposed to occur in Option 4. From what I can tell, you'd need to redefine the .getLayout for every page. I'm not sure how the logic for nesting is incorporated into further urls.
Here's the code from the article
// /pages/account-settings/basic-information.js
import SiteLayout from '../../components/SiteLayout'
import AccountSettingsLayout from '../../components/AccountSettingsLayout'
const AccountSettingsBasicInformation = () => <div>{/* ... */}</div>
AccountSettingsBasicInformation.getLayout = page => (
<SiteLayout>
<AccountSettingsLayout>{page}</AccountSettingsLayout>
</SiteLayout>
)
export default AccountSettingsBasicInformation
// /pages/_app.js
import React from 'react'
import App from 'next/app'
class MyApp extends App {
render() {
const { Component, pageProps, router } = this.props
const getLayout = Component.getLayout || (page => page)
return getLayout(<Component {...pageProps}></Component>)
}
}
export default MyApp
For example, say AccountSettingsBasicInformation.getLayout is /settings/, how would I use this template to produce something at /settings/username
P.S. If someone has done something in the past they'd recommend over this, I'm open to ideas.
Yes, you have to redefine the getLayout function to every page. As long as the SiteLayout component stays “unchanged” (eg.no props change) the rendered content in that layout component (not the page content itself) stays persistent. This is because React wont rerender that component.
I used Adam’s article when I was building next.js lib for handlin modal routes. You can check the example folder where you can see I am defining the getLayout property on every page which should be rendered with layout.
Example: https://github.com/svobik7/next-bodies/tree/master/example

Is there a way to execute code from a ES6 class file before it is even referenced it?

I'm not an expert on JS and I have inherited a React app with dozens and dozens of components.
I want to do something that in Java is trivial but I can't find the way in ES6.
I want to build a registry of most of those components and I'm looking for an approach to have each class register itself so it can be looked up dynamically by a key.
So I build a registry class like this
let registry = [];
export default class Registry {
static register(component) {
if (!registry.find(x => x.key == component.key))
registry.push(component);
}
}
And on each component class, I tried to register itself doing something like this:
import Registry from './Registry.jsx';
import React from 'react';
export default class Component extends React.Component {
... body of the component ...
}
Registry.register( { key: 'ComponentX', component: Component });
But it doesn't work because Registry is undefined.
In Java would be something like:
class Component {
....
static {
Registry.register('ComponentX',Component.class);
}
....
}
The only alternative I found is to create a static list of all components but that chokes with our current distributed approach to development
Thanks a lot
Edit
Thanks guys. I'd managed to get a step closer to the solution.
Using this:
let registry = new Map();
export function register(key, component) {
return registry.set(key, component);
}
import { register } from './Registry.jsx';
export default class Component extends React.Component {
static entry = register(key, component);
... body of the class ...
}
Using this scheme, the register function is invoked but the registry variable is undefined. I just need to find out how to have it defined at the time of the invocation of the register function.

Can you import a file which already contains reactDOM render calls?

I have a legacy enterprise application which contains numerous components which are rendered to multiple anchor points on the page. example below
modals.js
import etc
class MyModal extends Component {
render() {
return <span>a modal</span>
}
}
var modals = $('.react__modal');
if (modals.length) {
modals.each(function() {
ReactDOM.render(<MyModal />,this);
});
}
now suppose I have multiple areas to this app such as admin.js, frontend.js, account.js, could I import modals.js in some what to be included within all these areas or would I have to export the class and then have multiple declarations of my ReactDOM.render in each of my areas.
I have approximately 100 components like this, and I'd rather not have to duplicate the render across all areas (6 in total).
Currently using gulp to compile, but in the process of moving to webpack (using laravel mix).
You could try to use export:
export default class MyModal extends Component
Then in other components you can import it and use:
import MyModal from "./yourPathToComponent"

Use react without a router component

If I want to make a web application using reactjs that is not a single page.
Should I compile all the react code into a single file and load it on all pages of the application, then use the function that I expose to render the necessary components?
Example of an html file
<div id="Clock" data-react="Clock"></div>
<div id="HelloWorld" data-react="HelloWorld"></div>
example of index.js
import React from 'react';
import ReactDOM from 'react-dom';
import Clock from './Clock';
import HelloWorld from './HelloWorld';
import OtherComponent from './OtherComponent';
const APPS = {
Clock,
HelloWorld,
OtherComponent
};
const MyReactRender = react => {
let component = react.getAttribute('data-react');
let App = APPS[component];
if(App != undefined) {
ReactDOM.render(<App />, document.getElementById(component));
}
}
document.querySelectorAll('[data-react]').forEach(MyReactRender);
I'd see two ways, of increasing quality and difficulty. In both cases, you use good old anchors elements to redirect the page to a url, to which different templates correspond.
Manually check for the existence of divs id's
In this case, each template includes the same javascript bundle that contains everything in the app and a single element with an id corresponding to the specific component. The idea is to check wether or not an element is present in the page, then activate its corresponding react component if it is.
if (document.getElementById('component-root')) {
ReactDOM.render(<Component />, document.getElementById('component-root'));
}
On the up side, it's quite easily implemented. On the down side, the bundle will always get bigger and bigger, and the list of ifs grows each time you add a new "page".
Separate your modules in actual bundles
Different bundle managers exist, but I'd recommend using Webpack to create multiple bundles that contain only specific part of your application. Then, each template contains only the corresponding div element, as well as that specific bundle.
<head><script src="/js/clock.js"></head>
<body><div id="root-clock"></div></body>
<head><script src="/js/otherComponent.js"></head>
<body><div id="root-other-component"></div></body>
How to package multiple bundles with webpack is out of the scope of this answer, but look here.
I've tried making a react application without a router. I used ternary operators to switch from component to component.
// App Component
class App extends Component {
constructor(props) {
super(props)
this.state = {
inClockComponent: true,
inHelloWorldComponent: false,
inOtherComponent: false
}
}
render() {
const {inClockComponent, inHelloWorldComponent, inOtherComponent} = this.state
return (
<div>
{
inClockComponent
? <Clock> : inHelloWorldComponent
? <HelloWorld> : inOtherComponent ? <OtherComponent> :
<div>No Component Here</div>
}
</div>
}
You could pass a function from the App component that would change the display state to each child component of App
Example
// in App Component
showHelloWorldComponent() {
this.setState({
inClockComponent: false,
inHelloWorldComponent: true,
inOtherComponent: false
)}
}
You insert that function onto a button that would navigate to a different component
Example
// in Clock Component
render() {
return (
<div>
<h2>Time is 5:15 P.M.</h2>
<button onClick={this.props.showHelloWorldComponent}>
Go To Hello World
</button>
)
}
It's a messy solution, and I wouldn't suggest using it in a big application, but I hope this answers your question!

import or require React components dynamically

I'm trying to import / require components dynamically, but somehow when I do it React complains. The require function does find it, but React throws an error saying it is missing some functions 't' etc.. All of this in an electron app.
I have a wizard setup (that is working, but not so elegant I think), where each page has it's own layout and jsx component. If I'd like to add a new page, I don't want to manage x-number of files, and at the moment I have to due to the setup I have currently. Below you can find what I want to achieve and what I'm doing now to achieve it. If there are any suggestions, code smells or better options please let me know as I'm quite new to React and ES2015 (as I'm from a C# background).
What I'm trying to achieve
export default class WizardPageContainer extends Component {
// Constructor
constructor(props) {
super(props);
}
// Render
render() {
const WizardPage = require(`./path/to/${this.props.step.id}`);
return (
<WizardPage step={this.props.step} />
);
}
}
How I'm currently doing it : which means I have to declare the imports / files first on top of the "WizardPageContainer" component.. Which means extra work and prone to errors/forgetting things. I should add, this code is working now ok, but I don't think this is elegant/future proof:
/* PAGES */
import WizardPage_Welcome from './pages/0.wizard.welcome';
import WizardPage_SystemCheck from './pages/1.wizard.systemCheck';
import WizardPage_SignIn from './pages/2.wizard.signIn';
import WizardPage_ExamCode from './pages/3.wizard.examCode';
import WizardPage_TakeExamination from './pages/4.wizard.takeExamination';
import WizardPage_Close from './pages/5.wizard.close';
const pages = [
WizardPage_Welcome,
WizardPage_SystemCheck,
WizardPage_SignIn,
WizardPage_ExamCode,
WizardPage_TakeExamination,
WizardPage_Close
];
/*/********************************************************************///
/* ******************************************************************** */
/* COMPONENT */
export default class WizardPageContainer extends Component {
// Constructor
constructor(props) {
super(props);
}
// Render
render() {
const WizardPage = pages[`${this.props.step.id}`];
return (
<WizardPage step={this.props.step} />
);
}
}
/*/********************************************************************///
I think it is about the "default". i have problem like this. Can you check this code;
https://github.com/robeio/robe-react-admin/blob/master/src/app/HasAuthorization.jsx#L10
Also you can check the example usage;
https://github.com/robeio/robe-react-admin/blob/master/src/app/HasAuthorization.jsx#L26
Your const pages needs to be an object, not an array.
You can see a working version I made of this here:
https://github.com/Frazer/meteor-react-nav/blob/master/lib/jsx/App.jsx
Best advice: Use Webpack to handle your imports, it's way more efficient than we could ever be.

Categories

Resources