ReactJS - After component mounts need to import/rerun local javascript file - javascript

Need to import "validation.js" file within another javascript file in reactjs once the main file render method is completes it execution
import './Validations';
should render this JS file once the main component's render method complete its execution

What you're trying to achieve is not really the way react likes to behave and probably is a mistake. if you need some extra functionality to be available in your component you could define a class, put your external logic in there and then instantiate an object from that class in your component's constructor or render method, and use whatever functionality you need in from there.

You can use react-loadable library to lazy load javascript file.
import Loadable from 'react-loadable';
const LoadableTest = Loadable({
loader: () => import('./validations.js'),
loading() { // you could write your spinner while the file is being loaded.
return <div>Loading...</div>
}
});
class MyComponent extends React.Component {
render() {
return <LoadableTest/>;
}
}

Related

lazy() loading not loading non component js file in react

I am trying to lazy load constant file in react. This constant file is not react component just simple javascript files like below :
// constant.js
export const customFunction = () => {
}
// component.js
const {
customFunction,
} = React.lazy(() => import('./constant.js'));
This I am not able to find in browser under developer tools source option. Also due to this getting customFunction undefined error. This code work if do normal import. customFunction using under useEffect()
import {
customFunction
} from './constant.js';
Do not wrap import statement inside React.lazy. Instead only use import() which returns a Promise and it gets resolved to the contents of the mentioned file
Here is a working example

Javascript working before page rendering in Gatsby

I try to convert a HTML template (Bootstrap 5) to Gatsby template. CSS and pages working expected but in HTML template there is a main.js file and it need to load after page rendered.
I modify the main.js file like that;
import { Swiper } from "swiper/swiper-react.cjs.js";
import GLightbox from "glightbox/dist/js/glightbox.min.js";
import AOS from "aos";
AOS.init();
export const onClientEntry = () => {
window.onload = () => {
console.log("deneme");
/*rest of code*/
};
};
In here I try two way. One of them, I create main.js file inside src->components->assets->js folder. Then in layout.js I try to import that file.
import React from "react";
import PropTypes from "prop-types";
import { Breadcrumb } from "gatsby-plugin-breadcrumb";
import Header from "./partials/header";
import { Helmet } from "react-helmet";
import useSiteMetadata from "./hooks/siteMetadata";
import "./assets/css/style.css";
import "./assets/js/main.js"
However in here in debug not hit the any method inside onClientEntry. So I decide to change my way.
Secondly, I try to add code inside main.js to gatsby-browser.js. That's time again getting Cannot read property 'addEventListener' of null because of html is not ready yet.
My file structure:
window (and other global objects like document) are not available during the SSR (Server-Side Rendering) because this action is performed by the Node server (where for obvious reasons there's no window, yet) so you can't access directly to onload function. In addition, accessing these global objects outside the scope of React (without hooks) can potentially break React's hydration process.
That said, you have a few approaches:
Using React hooks. Specifically, useEffect with empty dependencies ([]) fits your specifications, since the effect will be fired once the DOM tree is loaded (that's what empty deps means):
const Layout = ({children}) => {
useEffect(()=>{
mainJs();
}, [])
return <main>{children}</main>
}
Assuming that your ./assets/js/main.js file has a mainJs() function exported, this approach will load it when the DOM tree is loaded. For example:
const mainJs= ()=> console.log("deneme");
The console.log() will be triggered when the HTML tree is built by the browser. Tweak it to adapt it to your needs.
Adding a window-availability condition like:
export const onClientEntry = () => {
if(typeof window !== 'undefined'){
window.onload = () => {
console.log("deneme");
/*rest of code*/
};
}
};
Alternatively, you can output the console.log directly in your onClientEntry, depending on your needs:
export const onClientEntry = () => {
console.log("deneme");
/*rest of code*/
};
You can even combine both approaches by adding a useEffect in your gatsby-browser if it works for you.

Next.js: How to dynamically import external client-side only React components into Server-Side-Rendering apps developed?

I know this question has been asked multiple times before but none of the solution seems to work.
I'm trying to use the library 'react-chat-popup' which only renders on client side in a SSR app.(built using next.js framework) The normal way to use this library is to call import {Chat} from 'react-chat-popup' and then render it directly as <Chat/>.
The solution I have found for SSR apps is to check if typedef of window !=== 'undefined' in the componentDidMount method before dynamically importing the library as importing the library normally alone would already cause the window is not defined error. So I found the link https://github.com/zeit/next.js/issues/2940 which suggested the following:
Chat = dynamic(import('react-chat-popup').then(m => {
const {Foo} = m;
Foo.__webpackChunkName = m.__webpackChunkName;
return Foo;
}));
However, my foo object becomes null when I do this. When I print out the m object in the callback, i get {"__webpackChunkName":"react_chat_popup_6445a148970fe64a2d707d15c41abb03"} How do I properly import the library and start using the <Chat/> element in this case?
Next js now has its own way of doing dynamic imports with no SSR.
import dynamic from 'next/dynamic'
const DynamicComponentWithNoSSR = dynamic(
() => import('../components/hello3'),
{ ssr: false }
)
Here is the link of their docs: next js
I've managed to resolve this by first declaring a variable at the top:
let Chat = ''
then doing the import this way in componentDidMount:
async componentDidMount(){
let result = await import('react-chat-popup')
Chat = result.Chat
this.setState({
appIsMounted: true
})
}
and finally render it like this:
<NoSSR>
{this.state.appIsMounted? <Chat/> : null}
</NoSSR>
You may not always want to include a module on server-side. For
example, when the module includes a library that only works in the
browser.
Import the library normally in child component and import that component dynamically on parent component.
https://nextjs.org/docs/advanced-features/dynamic-import#with-no-ssr
This approach worked for me.

How to execute the js file once the react component is rendered?

I have 4 react components header,modal,container,index. In index.js I'm rendering all the components. Now, I have one problem My HTMl page is using one js file(home.js). It is executing the before the DOM loads. So, it is not getting any properties of the DOM so it is failing. So, How I can the execute that js file once the DOM is loaded?
Wrap your home.js code with a global function and call to that function in componentDidMount life cycle method of your root React component.
So your home.js file will look something like this.
window.executeHome = function() {
// your curren home.js code goes here
}
and inside the componentDidMount method of your root React component, you can call above method to make sure that you are running home.js code after loading the React components.
componentDidMount() {
window.executeHome();
}
However, consider this as a workaround and it's usually not something recommended. The better approach would be writing your home.js code also inside a React component.
please try
componentDidMount() {
}
componentDidMount() automatically called after render() method.

Render isomorphic React component which requires window object

I have an isomorphic React application, with components being rendered on the server-side. I wish to use a 3rd party React component: (GraphiQL), and am rendering as such:
var GraphiQLComponent = React.createElement(GraphiQL, { fetcher: graphQLFetcher}, "");
router.get('/graphiql', function (req, res) {
res.send(ReactDOMServer.renderToString(GraphiQLComponent));
});
However, this component uses the window object: window.localStorage and window.addEventListener, and when I try to load the page in the browser, I get the error:
ReferenceError: window is not defined
Can I render React components which use the window object, on the server? If so, what do I need to do to resolve this error?
Don't use libraries that depend on window in your components.
or
Only use these libraries in componentDidMount and exclude them for prerendering (make sure your component don't render different in prerendering or it doesn't work).
I figured I shouldn’t import the library outside the class definition, but instead require it in the componentDidMount method or a called method thereof.
So, instead of:
...
import MyWindowDependentLibrary from 'path/to/library';
...
export default class MyClass extends React.Component {
...
componentDidMount() { MyWindowDependentLibrary.doWork(); }
...
}
I did:
// removed import
...
export default class MyClass extends React.Component {
...
componentDidMount() {
const MyWindowDependentLibrary = require( 'path/to/library' );
MyWindowDependentLibrary.doWork();
}
...
}
Yes you can!
Just do not run that piece of code until window is defined!
I also imagine you could use those functions in a componentDidMount() lifecycle function.
if (window !== 'undefined') {
// do your window required stuff
}
I've used this multiple times in components being rendered server-side, and it works like a charm.

Categories