ComponentDidMount() in Server-side render - node.js

I'm trying to server-side render my webpage for better performance but am running into an issue where my page's components componentDidMount()s aren't getting called.
For example, this is my main template file:
import React from 'react';
import Cube from './components/Cube/Cube.jsx';
class Index extends React.Component {
render() {
return (
<html>
<head>
<title>{this.props.title}</title>
</head>
<body>
<Cube />
</body>
</html>
);
}
}
And my Cube.jsx:
import React from 'react';
class Cube extends React.Component {
componentDidMount() {
console.log("Hey!");
}
render() {
return (
<div>
<h1>Hello</h1>
</div>
);
}
}
export default Cube;
I'm not seeing "Hey!" getting logged out in my pm2 logs nor in my chrome console even though I'm seeing the <h1>Hello</h1> when the page loads. This is stopping me from having any sort of logic for my component.
How do I get around this problem and make my subcomponents's componentDidMount() get called? Note I'm using express-react-views for my server-side rendering.

I think the only lifecycle hook that will be called server side is componentWillMount as explained here
Even then you would not see output on Chrome's console. You are only likely to see it in your node logs.
Let me know if this answers your question.

Problem is as I my self found out few days ago using Next.js that React application is not mounted. What that means is that Server Side Rendering is exactly that. React app is 'rendered' aka static HTML file is created on the server, and served to the browser. But in that process React is not mounted and no hooks are fired. Maybe componentWillMount I am not sure and have not tested.

Related

Use React to build parts of the application features

Consider having a web application that is based on a complex platform, however, you can design HTML Forms using its designer, and insert standard HTML elements, one of which is HTML Component. You can use this component to add HTLM/JavaScript code as usual.
I followed a tutorial to create a react app without using create-react-app. I managed to develop a sample React app using NodeJs, Babel, and Webpack and managed to deploy the final bundled JavaScript main.js on the target application. All worked fine. Below are the main two files with the source code:
index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
ReactDOM.render(<App />, document.querySelector("#root"));
App.js
import React, {useState} from "react";
const App = () => {
let [counter, setCounter] = useState(0);
const increment = () => {
counter++;
setCounter(counter);
}
return <div>This was created from React and Hello World!
<h1>This is a test Header</h1>
<button onClick={increment}>Click here to increment</button>
<br/>
<span>{counter}</span>
</div>
}
export default App;
The Form HTML Component in the Target Web Application:
<div id="root">This Text should be replaced by the React App</div>
<script src="./target/app/path/public/main.js"></script>
Mind you that I ran the command npm run build and it generated the final script main.js which is deployed to the target application.
I am planning to start using React to build specific components for example a combination of Drop-Down Fields and Grid elements which are populated using REST APIs.
The problem is that I have to have one entry JavaScript source file that will render the component using ReactDOM.render(<App />, document.querySelector("#root")), and if I develop say 100 components, but not all of them will be rendered when any Application Form is loaded. I think if the React render() function is invoked and the target DOM element is not present, then it will throw an error (I am not sure though).
So the question is how to design the application so that I can follow the above approach and ensure that the intended React Component will kick in only when the related Form is loaded or active.
I am thinking to import all the Components in index.js and develop a method to detect if the Form is active and needs a component, then it will invoke the function ReactDOM.render(<MyComponent />, document.querySelector("#MyComponentId")).
I am not sure how to implement that and I need help. I appreciate your feedback.

How can I refresh the whole react application and saving cached

I created mern stack react application, using nodejs and express as a server. I want to recieve cookie with jwt token from the server and afterwards refresh the whole page completely and save the cookie. I tried to refresh the page by using window.location.reload(false) and also useHistory.get(0) but both of them refresh the page endless times till I deleted the token and then it stoped refreshing. I also tried to write window.stop() right after window.location.reload(false) but then it did not refresh the window at all.
How an I refresh the whole window only once?
It is worth to mention that I don't have so much experience with react, so I would really appreciate your help.
Thank you.
React doesn't like when you refresh the page yourself. It prefers to handle that by itself. Using the useState hook will auto-refresh the page when the state changes but you can also use the useEffect hook to change the value without causing re-renders.
So what you might want to do is get the cookie, then use the setState you created and the change of value will cause a refresh, while also storing the cookie.
If you want to have the navbar and the page change based on login, you could just switch pages. So have one page where you login with one navbar, then, when logged in, change the page.
Heres an example for an easy way to switch between pages:
import {useState} from 'react';
import ReactDOM from 'react-dom/client';
function Index() {
const [login, setLogin] = useState(false)
if (login) {
return (
<div >
<h1> Logged in ! </h1>
</div>
)
} else {
return (
<div >
<button onClick={() => {
setLogin(true);
}>Login</button>
</div>
)
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render( <Index/> );
This re-renders everything on the page when swapping
It is probably better to do it in a format like this though:
w3Schools Example with router

Hide other code in the app.js in the login page of a vue app

I'm creating an app using laravel + vue. Vue loads all the javascript codes in the app.js even in the login page in which the user is not yet authenticated. I don't want to expose all the js codes just yet until user is logged in. Is there any way that I can only show the necessary codes for the login page and not expose all the js code of the app? I'm doing this to also limit the size of app.js being downloaded for the login page to improve page loading time too.
If you're using Laravel mix, you can add a new entry point for your login script.
mix.js('resources/assets/app/js/app.js', 'public/app/js')
.js('resources/assets/app/js/login.js, 'public/app/js);
So, you can add a #yield statement in your base layout to place scripts declared in the page view.
base.blade.php
<html>
<head>
<title>App Name - #yield('title')</title>
</head>
<body>
#section('sidebar')
This is the master sidebar.
#show
<div class="container">
#yield('content')
</div>
#yield('scripts')
</body>
</html>
login.blade.php
#extends('layouts.base')
#section('title', 'Page Title')
#section('content')
<p>This is my body content.</p>
#stop
#section('scripts')
<script src="{{ mix('app/js/login.js') }}"></script>
#stop
Edited
For a SPA you can have another bundled entry point to just define the Login component:
Vue.component('login-form', {
... component code here
})
You can use vue-plugin-load-script to load the login.js script in the beforeEach method from Vue router. So the component will be available before render the login page.
router.beforeEach(async (to, from, next) => {
if (to === 'login'){
await Vue.loadScript('login entry point url here')
}
next();
});
Also, you can do it inside the page using the beforeMount hook. Here an example using a fake promise and entry point.
https://jsfiddle.net/7oj2sxun/3/
If you're using Vue CLI, it already supports lazy loading with dynamic imports.
Here a detailed article:
https://blog.logrocket.com/lazy-loading-in-vue-js/

React js : Rendering multiple index html in a single page applications

I am developing an E - Commerce website in React and Node.js. I am facing two problems described below.
I have two different master .html files for admin side and front end side. Hence I am using builtin React admin template in which index.html is loading on project start. My problem is how can I load another master .html for front end design?
I want to use Node.js as the back end. Hence I can not integrate node.js with React front or admin side which will run if the React application runs.
Any suggestions or solution steps will be highly appreciated.
Here's a very basic concept of the first idea:
const AdminIndexPage = children => (<section className="AdminIndexPage">{children}</section>)
const PublicIndexPage = children => (<section className="PublicIndexPage">{children}</section>
const App = props => {
if(props.indexPageToShow === 'admin'){
return <AdminIndexPage {...props} />
}else{
return <PublicIndexPage {...props} />
}
}
Here's a very basic concept of the second idea:
index.html
<html>
<head>
<script src="index.js"></script>
</head>
<body>
<div id="AdminPageIndex"></div>
<div id="PublicPageIndex"></div>
</body>
</html>
index.js
import {AdminPageIndex, PublicPageIndex} from './pages'
ReactDOM.render(AdminPageIndex, document.getElementById('AdminPageIndex'))
ReactDOM.render(PublicPageIndex, document.getElementById('PublicPageIndex'))

ReactDOM renderToStaticMarkup renders <noscript></noscript>

I have a universal app with React Router.
let html = ReactDOM.renderToStaticMarkup(
<Provider store={store}>
<RoutingContext {...renderProps} />
</Provider>
);
The above is my React markup.
When I view my page source I see:
<div id="app">
<noscript></noscript>
<div id="home">
<h2>Home</h2>
</div>
</div>
What is this noscript tag? Can I get rid of it?
You seem to have confused Redux Router with React Router in the question.
The fragment of code you are running is for React Router, so I’ll assume that’s what you’re using.
React renders <noscript> for components that returned null during rendering.
Could it be that in your route configuration, there is no component matching that particular route?
Or that your component returned null?
It is hard to say more without seeing the full source code.

Resources