ReactGA.initialize must be called first - javascript

I am getting the following warning multiple times (for multiple pages) despite me initializing at the root of my app. This makes me wonder if google analytics is even working properly?
[react-ga] ReactGA.initialize must be called first or GoogleAnalytics should be loaded manually
I am using ReactGA to handle my google analytics tags, and I cannot get it to work. According to the documentation and a handful of other questions about this online, all I need to do is insert this at my application root:
App.js:
import ReactGA from 'react-ga';
ReactGA.initialize('G-xxxxxxxxxx');
const app = () => (
// Root level components here, like routing and navigation
)
I am using Server Side Rendering, so I am making sure the window object exists before tracking. This line is put at the end of my imports on each of my pages:
example page.js:
import ReactGA from 'react-ga';
if (typeof(window) !== 'undefined') {
ReactGA.pageview(window.location.pathname + window.location.search);
}
function page() {
return(<div className="page">Hello, World</div>)
}
export default page;
At this point, there isn't a lot of information on how to set up Google Analytics for SSR applications, so I'm not entirely sure what I need to do to get this working. Any help is appreciated!

I finally found the solution after a lot of tinkering with potential solutions. Since pageview was being fired before initialize could finish, I tired delaying pageview as much as I could by placing it in componentDidMount(). That implementation looks like this:
App.js:
//imports
import ReactGA from 'react-ga';
ReactGA.initialize('UA-xxxxxxxxx-x');
const App = () => (
<div className="App">
<Navigation />
<AppRouting />
</div>
);
Page.js:
import ReactGA from 'react-ga';
class MyPage extends React.Component {
componentDidMount() {
ReactGA.pageview(window.location.pathname + window.location.search);
}
render() {
return(
<Component />
);
}
}

In functional components the same can be done using the useEffect hook
useEffect(() => {
ReactGA.pageview(window.location.pathname + window.location.search);
}, ['your dep'])

Related

ReactJs/Framer Motion is slow on mobile

My ReactJs app works well on PC but becomes laggy on mobile, not sure but I think it's the framer motion library that is causing this framing problem.
I have been looking for a solution to this problem but could not find the answer.
This this the link to the site https://trayfoods.pages.dev
https://dev.to/nilanth/how-to-reduce-react-app-loading-time-by-70-1kmm
https://proxify.io/articles/build-large-scale-React-apps#6-obey-naming-conventions
Since my 2 previous answers you have tried already , maybe then try to reduce the react app loading time by lazy loading the pages themselves and components
Note:
makesure your App.js to App.jsx or it wont work
//For instance
const Dashboard = lazy(() => import('components/Dashboard'));
How i applied it
import { lazy } from "react";
//inside my components/i have an index.js file
export const NavbarLazy = lazy(()=> import('../components/Navbar/Navbar'));
//inside App.jsx
import {NavbarLazy } from './components/index';
function App() {
return (
<div className="App">
<NavbarLazy />
</div>
);
}

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

NextJS - Load external script on page component load

I've migrated an old website to Nextjs and i need the scripts to load every time a page component is loaded. But if i use the next/link component to navigate between pages, the scripts run only the first time the page is loaded. I've tried putting the inside the Head component in every page, but it still doesn't work. There is a workaround for this?
The two solutions to loading external scripts in Next.js seem to be to:
Load them using a combination of _document.js and next.config.js
_document.js
<script
type="text/javascript"
dangerouslySetInnerHTML={{ __html: process.env.jquery }}
></script>
next.config.js
const fs = require("fs")
module.exports = ({
env: {
jquery: fs.readFileSync("./public/js/jquery.js").toString(),
}
})
Reference: https://stackoverflow.com/a/65349130/2167762
Load them using React's useEffect hook, like with a custom useScript hook
/pages/index.js
import { useEffect } from "react"
const useScript = (url) => {
useEffect(() => {
const script = document.createElement("script")
script.src = url
script.async = true
document.body.appendChild(script)
return () => {
document.body.removeChild(script)
}
}, [url])
}
//export default function Home({ posts }) {
export default function Home() {
useScript("js/jquery.js")
return <p>Component</p>
}
Reference: https://stackoverflow.com/a/34425083/2167762
So which should you use?
The first seems to work "great" but is actually quite buggy -- I only get the JavaScript working sometimes after refreshing in development, and never in production.
(This would correspond to your problem with the scripts not loading when navigating with <Link>.)
The latter seems to work much better, although sometimes when I refresh in dev the scripts seem to load out of order, potentially causing runtime errors.
In production, however, the scripts seem to load & run consistently. I haven't explicitly tested <Link>, but it should work with the useEffect() method.
It'll be helpful to see the scripts you're loading. I faced a similar issue whiles using styled components in the version 9 of Nextjs. It had something to do with the server side rendering. Usually, using the Head should work. ie.
import Head from "next/head";
const HeadComponent = () => {
return (
<>
<Head>
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
</Head>
</>
);
};
You could also choose to dynamically import the scripts to the root of your app using:
import dynamic from "next/dynamic";
function MyApp({ Component, pageProps }) {
const Script = dynamic(() => import("../Script"));
return (
<>
<Component {...pageProps} />
<Script />
</>
);
}
export default MyApp;
I realised that the above makes all resources load in Nextjs

NextJs router seems very slow compare to React Router

I have a website built in React Js and the same one on Next Js as well.
The problem which I am facing right now is, the router seems very slow in the nextJs compare to react-router-dom, It's taking almost 2-3 seconds to change the route.
Here are the URLs where you can feel the difference between the performance by moving around different pages.
https://cutt.ly/mhbPkOE (React Router Dom) vs
https://cutt.ly/BhbPvHv (NextJs)
I had read some comments on Github where few experts are saying that It will resolve in production. but It looks same in production too.
Please have a look at the following code
_app.jsx
// import App from 'next/app'
import React from "react"
import Router from 'next/router';
import "../static/sass/application.scss";
import "bootstrap/dist/css/bootstrap.min.css";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import 'semantic-ui-css/semantic.min.css'
import { wrapper } from "../../redux/utils/store"
import App from 'next/app';
// A simple component that we created
import {LoaderOverlay} from '../components/Reusable'
class MyApp extends App {
constructor(props){
super(props)
this.state = {
isLoading: false,
}
Router.onRouteChangeStart = (url) => {
// Some page has started loading
this.setState({
isLoading: true,
}) // set state to pass to loader prop
};
Router.onRouteChangeComplete = (url) => {
// Some page has finished loading
this.setState({
isLoading: false,
}) // set state to pass to loader prop
};
Router.onRouteChangeError = (err, url) => {
this.setState({isLoading: false,})
};
};
render() {
const {Component, pageProps} = this.props
return (
<div>
{this.state.isLoading ? (
<LoaderOverlay/>
) : (
<Component {...pageProps} />
)}
</div>
)
}
}
export default wrapper.withRedux(MyApp);
_document.jsx
import Document, { Html, Head, Main, NextScript } from 'next/document'
class MyDocument extends Document {
static async getInitialProps(ctx) {
const originalRenderPage = ctx.renderPage
ctx.renderPage = () =>
originalRenderPage({
// useful for wrapping the whole react tree
enhanceApp: (App) => App,
// useful for wrapping in a per-page basis
enhanceComponent: (Component) => Component,
})
// Run the parent `getInitialProps`, it now includes the custom `renderPage`
const initialProps = await Document.getInitialProps(ctx)
return initialProps
}
render() {
return (
<Html lang="en">
<Head>
<link async rel="stylesheet" href="//cdn.jsdelivr.net/npm/semantic-ui#2.4.1/dist/semantic.min.css"/>
</Head>
<body>
<div className={'main-wrapper'}>
<Main />
</div>
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
Development mode (next dev) is much slower because the routes aren't pre-built.
All delay related to routing assuming you don't have any server side blocking data requirements via getInitialProps, getServerSideProps, should not be present when running production mode with next build followed by next start.
Not sure if you have found a fix for this yet, but I came across this article about "shallow routing". I can't see much improvement in my application when using it, but maybe it will help someone else:
https://nextjs.org/docs/routing/shallow-routing
Hey I think you are in your production mode.
That's why it is slow. But if you will host your site it will be pretty much like react only.
But then also if you want to routing fast
Then npm i next#4.2.3 --save will work fine..
to solve this issue followed the commands:
yarn build/nmp build
yarn start/npm start
I hope this will solve this issue

Next.js: Render dynamic pages customized based on requesting host

I want to render dynamic next.js pages with custom content / style based on the domain which requests the page.
Basically run one next.js app under multiple domains.
I know that I have to do some sort of custom routing, but don't know exactly how and how I can pass the host information to the requested page, so it fetches the matching data from a database.
You should be able to verify this in your pages/_app.jsx file static getInitialProps(context) method and use the context to verify where the request is coming from then return a flag to the component.
Example:
// pages/_app.js
import app from 'next/app';
export default class MyApp extends app {
static getInitialProps({ Component, router, ctx }) {
let pageProps = app.getInitialProps({ Component, router, ctx });
if (ctx.req.headers.host.match(/localhost/)) {
pageProps = {
...pageProps,
renderFrom: 'mydomain',
}
}
return { pageProps };
}
render() {
const { Component, pageProps } = this.props;
return (
<section id="app">
<Component {...pageProps} />
</section>
);
}
}
Note that I call app.getInitialProps to mimic the next/app component behaviour as in the source code here
In your pages/index.js you will have access to props.renderFrom and there you can display data.
// pages/index.js
import React from 'react'
const Home = props => (
<div>
Rendering content for domain: {props.renderFrom}
</div>
)
export default Home
Since you're verifying where the request comes from in _app.js this property will be available in all your containers (pages) so you can have the same routing for your application and just render data differently.
Tip: You could also use next-routes to manage the routing for the application, it's better than the out next comes with, and in here you have a custom server where you can manage your traffic as well.
Hopefully this helps you and points you in the right direction.
Here’s an example of hosting multiple domains on the same Next.js site (while maintaining multiple languages and static site generation/SSG), using Next.js’ i18n system:
https://github.com/tomsoderlund/nextjs-multi-domain-locale

Categories

Resources