After building nextjs app, chunk/pages/_app-.....js file size is too large - reactjs

I have a next js project that is created by create next app and modified _app.ts to this
import "../../public/assets/css/bootstrap.css";
import "antd/dist/antd.css";
import "../../public/assets/css/common.css";
import "../styles/globals.css";
import "../styles/builderGlobals.css";
import "../../public/assets/css/quiz.css";
import "../../public/assets/css/main.css";
import "../../public/assets/css/responsive.css";
import Head from "next/head";
import { wrapper } from "../app/store";
import { setUser } from "../Modules/Auth/authSlice";
import Layout from "../components/Layouts/layout";
import type { AppPropsWithLayout } from "../utils/types";
import { setNotifSettingsData } from "../Modules/Notifications/notificationsSlice";
import serverApi from "../utils/axios/serverApi";
import NextNProgress from "nextjs-progressbar";
import { useAppSelector } from "../app/hooks";
const MyApp = ({ Component, pageProps }: AppPropsWithLayout) => {
const favicon = useAppSelector(state => state.settingsData.favico_icon);
const getLayout =
Component.getLayout ??
((page) => (
<Layout>
<Head>
<link rel="shortcut icon" href={favicon || "/img/favicon.png"} />
</Head>
<NextNProgress /> {page}
</Layout>
));
return getLayout(<Component {...pageProps} />);
};
MyApp.getInitialProps = wrapper.getInitialAppProps(
(store) =>
async ({ Component, ctx }) => {
if (!ctx.req) {
return {
pageProps: {
...(Component.getInitialProps
? await Component.getInitialProps({ ...ctx, store })
: {}),
pathname: ctx.pathname,
},
};
}
try {
const { data: initialData } = await serverApi(
ctx,
`/settings/get-initial-site-data`
);
store.dispatch(setUser(initialData?.authUser));
store.dispatch(setNotifSettingsData(initialData?.siteSettings));
return {
pageProps: {
...(Component.getInitialProps
? await Component.getInitialProps({ ...ctx, store })
: {}),
pathname: ctx.pathname,
},
};
} catch (error) {
ctx.res.statusCode = 404;
ctx.res.end("Not found");
return;
}
}
);
export default wrapper.withRedux(MyApp);
But after running yarn build it created too large _app chunk. about 431kb
That is huge. How can I reduce this chunk? or am I doing anything wrong?
https://github.com/sakib412/sakib412/raw/main/WhatsApp%20Image%202022-10-13%20at%206.48.08%20PM.jpeg

Related

wrong Initial state in zustand in nextjs server side

I use zustand as a global state manager and I want use of the persisted states in server side of nextjs pages. but when I log the currently state values it will print default values (which the default values are null) and it does not log the updated states values.
The codes are here:
store.ts
/**
*? For more information about config zustand store in nextjs visit here:
*? https://github.com/vercel/next.js/blob/canary/examples/with-zustand/lib/store.js
*/
import { useLayoutEffect } from 'react';
import create, { StoreApi } from 'zustand';
import createContext from 'zustand/context';
import { devtools, persist, PersistOptions } from 'zustand/middleware';
import { createClinicSlice } from './slices/clinic';
import { createUserSlice } from './slices/user';
import type { IClinicSlice, IResetState, IUserSlice } from '$types';
const persistProperties: PersistOptions<any> = {
name: 'globalStorage',
getStorage: () => localStorage,
// ? should update version when app version updated
version: 0,
};
let store: any;
interface IInitialState {
clinics: null;
activeClinic: null;
user: null;
}
const getDefaultInitialState = (): IInitialState => ({
clinics: null,
activeClinic: null,
user: null,
});
const zustandContext = createContext<StoreApi<IClinicSlice & IUserSlice & IResetState>>();
export const Provider = zustandContext.Provider;
export const useStore = zustandContext.useStore;
export const initializeStore = (preloadedState: Record<string, any> = {}) => {
return create<IClinicSlice & IUserSlice & IResetState>()(
devtools(
persist(
(set) => ({
...getDefaultInitialState(),
...preloadedState,
// #ts-ignore
...createClinicSlice(set),
// #ts-ignore
...createUserSlice(set),
resetStore: () => set(getDefaultInitialState()),
}),
persistProperties
)
)
);
};
export function useCreateStore(
serverInitialState: Record<string, any>
): typeof initializeStore {
if (typeof window === 'undefined') {
return () => initializeStore(serverInitialState);
}
const isReusingStore = Boolean(store);
store = store ?? initializeStore(serverInitialState);
useLayoutEffect(() => {
// serverInitialState is undefined for CSR pages. It is up to you if you want to reset
// states on CSR page navigation or not. I have chosen not to, but if you choose to,
// then add `serverInitialState = getDefaultInitialState()` here.
if (serverInitialState && isReusingStore) {
store.setState(
{
// re-use functions from existing store
...store.getState(),
// but reset all other properties.
...(serverInitialState || getDefaultInitialState()),
},
true // replace states, rather than shallow merging
);
}
});
return () => store;
}
_app.tsx
import { useEffect } from 'react';
import CssBaseline from '#material-ui/core/CssBaseline';
import { ThemeProvider, jssPreset, StylesProvider } from '#material-ui/core/styles';
import i18n from 'i18next';
import { create } from 'jss';
import rtl from 'jss-rtl';
import type { AppProps } from 'next/app';
import Head from 'next/head';
import { I18nextProvider } from 'react-i18next';
import { ThemeProvider as SCThemeProvider } from 'styled-components';
import muiTheme from '$/assets/style/theme';
import { AuthProvider } from '$/components/contexts/auth';
import { ReactToastify } from '$/components/ReactToastify/ReactToastify';
import { Provider, useCreateStore } from '$store';
import '../../public/assets/style/index.css';
import 'leaflet/dist/leaflet.css';
import 'leaflet-geosearch/assets/css/leaflet.css';
import 'leaflet-geosearch/dist/geosearch.css';
import 'react-toastify/dist/ReactToastify.css';
import '$/utils/i18n.config';
const jss = create({
plugins: [...jssPreset().plugins, rtl()],
});
function MyApp({ Component, pageProps }: AppProps) {
useEffect(() => {
const jssStyles = document.querySelector('#jss-server-side');
if (jssStyles) {
jssStyles.parentElement!.removeChild(jssStyles);
}
}, []);
const createStore = useCreateStore(pageProps.initialZustandState);
return (
<>
<Head>
<meta
name="viewport"
content="minimum-scale=1, initial-scale=1, width=device-width, user-scalable=no"
/>
</Head>
<Provider createStore={createStore}>
<I18nextProvider i18n={i18n}>
<ReactToastify />
</I18nextProvider>
<StylesProvider jss={jss}>
<ThemeProvider theme={muiTheme}>
<SCThemeProvider theme={muiTheme}>
<CssBaseline />
<AuthProvider>
<I18nextProvider i18n={i18n}>
<Component {...pageProps} />
</I18nextProvider>
</AuthProvider>
</SCThemeProvider>
</ThemeProvider>
</StylesProvider>
</Provider>
</>
);
}
export default MyApp;
dashboard/index.tsx
import { useEffect } from 'react';
import type { NextPage } from 'next';
import { useRouter } from 'next/router';
import { PageScrollableArea } from '$/components/index';
import ClinicDashboardLayout from '$/components/layout/clinicDashboardLayout/ClinicDashboardLayout';
import { isNil } from '$/utils/stringUtils';
import ClinicDashboard from '$/view/clinic/Dashboard';
import withPrivateRoute from '$/view/hocs/withPrivateRoute';
import { CLINICS_PAGE_URL } from '$constant';
import { initializeStore, useStore } from '$store';
const Dashboard: NextPage = (props) => {
return (
<ClinicDashboardLayout>
<PageScrollableArea>
<ClinicDashboard />
</PageScrollableArea>
</ClinicDashboardLayout>
);
};
export default withPrivateRoute(Dashboard);
export function getServerSideProps() {
const zustandStore = initializeStore();
console.log(`===> zustandStore.getState() ===>`, zustandStore.getState());
// if (isNil(zustandStore.getState().activeClinic)) {
// return {
// redirect: {
// destination: CLINICS_PAGE_URL,
// permanent: true,
// },
// };
// }
return {
props: {},
};
}
I find out the store variable in store.ts file always is undefined and its value will not update as values are located in local storage
Does anybody have a similar experience with this issue?

Next JS code inside getInitialProps not executes after page reload

I'm integrating NextJS into my React app. I face a problem, on page reload or opening direct link(ex. somehostname.com/clients) my getInitialProps not executes, but if I open this page using <Link> from next/link it works well. I don't really understand why it happens and how to fix it. I have already came throught similar questions, but didn't find any solution which could be suitable for me.
Clients page code:
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { ClientsTable } from '../../src/components/ui/tables/client-table';
import AddIcon from '#material-ui/icons/Add';
import Fab from '#material-ui/core/Fab';
import { AddClientModal } from '../../src/components/ui/modals/add-client-modal';
import CircularProgress from '#material-ui/core/CircularProgress';
import { Alert } from '../../src/components/ui/alert';
import { Color } from '#material-ui/lab/Alert';
import { AppState } from '../../src/store/types';
import { thunkAddClient, thunkGetClients } from '../../src/store/thunks/clients';
import { SnackbarOrigin } from '#material-ui/core';
import { IClientsState } from '../../src/store/reducers/clients';
import { NextPage } from 'next';
import { ReduxNextPageContext } from '../index';
import { PageLayout } from '../../src/components/ui/page-layout';
const Clients: NextPage = () => {
const [addClientModalOpened, setAddClientModalOpened] = useState<boolean>(false);
const [alertType, setAlertType] = useState<Color>('error');
const [showAlert, setAlertShow] = useState<boolean>(false);
const alertOrigin: SnackbarOrigin = { vertical: 'top', horizontal: 'center' };
const dispatch = useDispatch();
const { clients, isLoading, hasError, message, success } = useSelector<AppState, IClientsState>(state => state.clients);
useEffect(() => {
if (success) {
handleAddModalClose();
}
}, [success]);
useEffect(() => {
checkAlert();
}, [hasError, success, isLoading]);
function handleAddModalClose(): void {
setAddClientModalOpened(false);
}
function handleAddClient(newClientName: string): void {
dispatch(thunkAddClient(newClientName));
}
function checkAlert() {
if (!isLoading && hasError) {
setAlertType('error');
setAlertShow(true);
} else if (!isLoading && success) {
setAlertType('success');
setAlertShow(true);
} else {
setAlertShow(false);
}
}
return (
<PageLayout>
<div className='clients'>
<h1>Clients</h1>
<div className='clients__add'>
<div className='clients__add-text'>
Add client
</div>
<Fab color='primary' aria-label='add' size='medium' onClick={() => setAddClientModalOpened(true)}>
<AddIcon/>
</Fab>
<AddClientModal
opened={addClientModalOpened}
handleClose={handleAddModalClose}
handleAddClient={handleAddClient}
error={message}
/>
</div>
<Alert
open={showAlert}
message={message}
type={alertType}
origin={alertOrigin}
autoHideDuration={success ? 2500 : null}
/>
{isLoading && <CircularProgress/>}
{!isLoading && <ClientsTable clients={clients}/>}
</div>
</PageLayout>
);
};
Clients.getInitialProps = async ({ store }: ReduxNextPageContext) => {
await store.dispatch(thunkGetClients());
return {};
};
export default Clients;
thunkGetClients()
export function thunkGetClients(): AppThunk {
return async function(dispatch) {
const reqPayload: IFetchParams = {
method: 'GET',
url: '/clients'
};
try {
dispatch(requestAction());
const { clients } = await fetchData(reqPayload);
console.log(clients);
dispatch(getClientsSuccessAction(clients));
} catch (error) {
dispatch(requestFailedAction(error.message));
}
};
}
_app.tsx code
import React from 'react';
import App, { AppContext, AppInitialProps } from 'next/app';
import withRedux from 'next-redux-wrapper';
import { Provider } from 'react-redux';
import { makeStore } from '../../src/store';
import { Store } from 'redux';
import '../../src/sass/app.scss';
import { ThunkDispatch } from 'redux-thunk';
export interface AppStore extends Store {
dispatch: ThunkDispatch<any, any, any>;
}
export interface MyAppProps extends AppInitialProps {
store: AppStore;
}
export default withRedux(makeStore)(
class MyApp extends App<MyAppProps> {
static async getInitialProps({
Component,
ctx
}: AppContext): Promise<AppInitialProps> {
const pageProps = Component.getInitialProps
? await Component.getInitialProps(ctx)
: {};
return { pageProps };
}
render() {
const { Component, pageProps, store } = this.props;
return (
<>
<Provider store={store}>
<Component {...pageProps} />
</Provider>
</>
);
}
}
);
Looking for your advices and help. Unfortunately, I couldn't find solution by myself.
This is the way Next.js works, it runs getInitialProps on first page load (reload or external link) in the server, and rest of pages that where navigated to with Link it will run this method on client.
The reason for this is to allow Next.js sites to have "native" SEO version.

NextJS: How to add screen loading for production build?

I want add screen loading in next js project. And I tried to do that with the Router component in next/router.
This is my _app.js in next.js project:
import {CookiesProvider} from 'react-cookie';
import App from 'next/app'
import React from 'react'
import {Provider} from 'react-redux'
import withRedux from 'next-redux-wrapper'
import withReduxSaga from 'next-redux-saga'
import createStore from '../src/redux/store'
import Router from "next/router";
import {Loaded, Loading} from "../src/util/Utils";
class MyApp extends App {
static async getInitialProps({Component, ctx}) {
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps({ctx})
}
return {pageProps}
}
render() {
Router.onRouteChangeStart = () => {
Loading()
};
Router.onRouteChangeComplete = () => {
Loaded()
};
Router.onRouteChangeError = () => {
Loaded()
};
const {Component, pageProps, store} = this.props;
return (
<CookiesProvider>
<Provider store={store}>
<Component {...pageProps} />
</Provider>
</CookiesProvider>
)
}
}
export default withRedux(createStore)(withReduxSaga(MyApp))
This is Loaded() and Loading() functions:
export const Loaded = () => {
setTimeout(() => {
let loading = 'has-loading';
document.body.classList.remove(loading);
}, 100);
};
export const Loading = () => {
let loading = 'has-loading';
document.body.classList.add(loading);
};
The code works well when the project is under development mode. But when the project is built, the loading won't disappear.
Do you know solution of this issue or are you suggesting another solution?
Using apollo client and react hooks you could do as follow.
Example:
import { useQuery } from '#apollo/react-hooks';
import gql from 'graphql-tag';
import { withApollo } from '../lib/apollo';
import UserCard from '../components/UserCard';
export const USER_INFO_QUERY = gql`
query getUser ($login: String!) {
user(login: $login) {
name
bio
avatarUrl
url
}
}
`;
const Index = () => {
const { query } = useRouter();
const { login = 'default' } = query;
const { loading, error, data } = useQuery(USER_INFO_QUERY, {
variables: { login },
});
if (loading) return 'Loading...'; // Loading component
if (error) return `Error! ${error.message}`; // Error component
const { user } = data;
return (
<UserCard
float
href={user.url}
headerImg="example.jpg"
avatarImg={user.avatarUrl}
name={user.name}
bio={user.bio}
/>
);
};
export default withApollo({ ssr: true })(Index);
More info here: https://github.com/zeit/next.js/tree/canary/examples/with-apollo
I added the following codes to a wrapper component and the problem was resolved.
componentDidMount() {
Loaded();
}
componentWillUnmount() {
Loading();
}

Next.js - Browser back gives--- TypeError: Cannot read property 'split' of undefined

My issue is similar to this..
https://github.com/zeit/next.js/issues/5604
I am using a custom server but I am not using any custom route handling. Even if remove the custom server and only run next i get this error while navigating back using browser back button.
As mentioned in https://github.com/zeit/next.js/blob/canary/errors/popstate-state-empty.md
I am not manipulating window.history in any place. Still I am getting this error.
I am using next/router for routing.
This is the _app.js code.
import React from 'react';
import App from 'next/app';
import Router from 'next/router';
import Head from 'next/head';
import withRedux from 'withRedux';
import { Provider } from 'redux-bundler-react';
import { ThemeProvider } from 'emotion-theming';
import { Global } from '#emotion/core';
import themeOne from 'ui-web/theme';
import { getCookie } from 'modules/authentication';
import configureStore from '../../src/store';
import { persist, cacheVersions } from '../../src/common';
import { appWithTranslation } from '../../i18n';
const makeStore = initialState => configureStore(initialState);
class MyApp extends App {
static async getInitialProps(props) {
const { Component, ctx, router } = props;
if (ctx.isServer && ctx.req.headers.cookie) {
const token = getCookie('authToken', ctx.req);
ctx.store.doSetAuthToken(token);
}
const pageProps = Component.getInitialProps
? await Component.getInitialProps(ctx, router.pathname)
: {};
return { pageProps };
}
render() {
const { Component, store, pageProps } = this.props;
return (
<Provider store={store}>
<ThemeProvider theme={themeOne}>
<Head>
<title>Learny</title>
<link
href='https://fonts.googleapis.com/css?family=Open+Sans:300,400,600&display=swap'
rel='stylesheet'
/>
</Head>
<Global
styles={theme => ({
body: {
margin: 0,
overflowX: 'hidden',
backgroundColor: theme.colors.background,
a: {
textDecoration: 'none',
},
},
})}
/>
<Component {...pageProps} />
</ThemeProvider>
</Provider>
);
}
}
export default withRedux(makeStore, { debug: false, persist, cacheVersions })(
appWithTranslation(MyApp)
);
server.js code sample is
/* eslint-disable #typescript-eslint/no-var-requires */
const express = require('express');
const next = require('next');
const nextI18NextMiddleware = require('next-i18next/middleware').default;
const nextI18next = require('./i18n');
const port = process.env.PORT || 3000;
const app = next({ dev: process.env.NODE_ENV !== 'production' });
const handle = app.getRequestHandler();
(async () => {
await app.prepare();
const server = express();
server.use(nextI18NextMiddleware(nextI18next));
server.all('*', (req, res) => handle(req, res));
await server.listen(port);
console.log(`> Ready on http://localhost:${port}`);
})();

next.js & material-ui - getting them to work

I'm giving next.js a spin and I can't get the simplest setup to work.
Here's my setup:
Relevant libs:
"react": "^16.2.0",
"react-dom": "^16.2.0",
"next": "^4.2.2",
"express": "^4.16.2",
"next-routes": "^1.2.0",
"material-ui": "^0.20.0",
server.js
const express = require('express')
const next = require('next');
const routes = require('./routes');
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handler = routes.getRequestHandler(app, ({req, res, route, query}) => {
render(req, res, route.page, query);
});
const server = express();
app.prepare()
.then(() => {
server.use(handler).listen(port, (err) => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
routes.js
const routes = module.exports = require('next-routes')();
routes
.add({name: 'walk', pattern: '/walk/:id'})
_document.js
import Document, { Head, Main, NextScript } from 'next/document';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
export default class extends Document {
static async getInitialProps(ctx) {
const props = await Document.getInitialProps(ctx);
const userAgent = ctx.req.headers['user-agent'];
return {
...props,
userAgent,
};
}
render() {
return (
<html>
<Head>
<title>ShareWalks</title>
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
<link rel="stylesheet" href="https://sharewalks.com/shared.css" />
</Head>
<body>
<MuiThemeProvider muiTheme={getMuiTheme({ userAgent: this.props.userAgent })}>
<div>
<Main />
<NextScript />
</div>
</MuiThemeProvider>
</body>
</html>
);
}
}
pages/index.js (this works)
import React, {Component} from 'react';
import Head from 'next/head';
class App extends Component {
static async getInitialProps(args) {
return {};
}
render() {
return (
<div>
<Head>
<title>ShareWalks</title>
</Head>
<p>Yup</p>
</div>
);
}
}
export default App;
pages/walk.js (it errors here)
import React, {Component} from 'react';
import {Head} from 'next/head';
class Walk extends Component {
static async getInitialProps({query}) {
console.log('query: ', query);
return {id: query.id}; //added to props
}
render() {
return (
<div>
<Head>
<title>Walking</title>
</Head>
<p>{`Walk #${this.props.id}`}</p>
</div>
);
}
}
export default Walk;
When I go to localhost:8080/walk/2 or localhost:8080/walk?id=2 I get the error. The console does print out the id as expected, but then this:
query: { id: '2' }
TypeError: Cannot read property 'toLowerCase' of undefined
at a.renderDOM (/home/terry/myProjects/PWA/sw-next/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:36:390)
at a.render (/home/terry/myProjects/PWA/sw-next/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:36:228)
at a.read (/home/terry/myProjects/PWA/sw-next/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:35:250)
at renderToString (/home/terry/myProjects/PWA/sw-next/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:44:6)
at renderPage (/home/terry/myProjects/PWA/sw-next/node_modules/next/dist/server/render.js:174:26)
at Function.getInitialProps (/home/terry/myProjects/PWA/sw-next/node_modules/next/dist/server/document.js:83:25)
at Function._callee$ (/home/terry/myProjects/PWA/sw-next/.next/dist/pages/_document.js:138:59)
at tryCatch (/home/terry/myProjects/PWA/sw-next/node_modules/regenerator-runtime/runtime.js:62:40)
at Generator.invoke [as _invoke] (/home/terry/myProjects/PWA/sw-next/node_modules/regenerator-runtime/runtime.js:296:22)
at Generator.prototype.(anonymous function) [as next] (/home/terry/myProjects/PWA/sw-next/node_modules/regenerator-runtime/runtime.js:114:21)
First guess is to try this with your server file - the biggest issue is that you aren't setting the id param on the route itself, so on the client side - it doesn't know to look for ID.
try this:
const express = require('express')
const next = require('next')
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare()
.then(() => {
const server = express()
server.get('/walk/:id', (req, res) => {
return app.render(req, res, '/walk', { id: req.params.id })
})
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(port, (err) => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
OK, getting material-ui to work with Next.js is for professionals. As far as I can tell, you can't use _document.js to set up material-ui. Can someone tell me why? Anyway, I wrote a higher order component thusly:
/components/hocs/withMui.js
import React, {Component} from 'react';
import getMuiTheme from 'material-ui/styles/getMuiTheme'
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
import injectTapEventPlugin from 'react-tap-event-plugin' //still needed?
import myTheme from 'styles/theme'
const muiTheme = myTheme;
export default function(NextPage) {
class outputComponent extends Component {
static async getInitialProps(ctx) {
const {req} = ctx;
const userAgent = req ? req.headers['user-agent'] : navigator.userAgent;
let pageProps = {};
if (NextPage.getInitialProps) {
pageProps = await NextPage.getInitialProps(ctx);
}
return {
...pageProps,
userAgent
}
}
render() {
let userAgent = this.props.userAgent;
return (
<MuiThemeProvider muiTheme={getMuiTheme({userAgent, ...muiTheme})}>
<NextPage {...this.props} />
</MuiThemeProvider>
);
}
}
return outputComponent;
}
and to use it with any page:
/pages/index.js
import React, {Component} from 'react'
import withMui from 'components/hocs/withMui';
import RaisedButton from 'material-ui/RaisedButton'
import Dialog from 'material-ui/Dialog'
import FlatButton from 'material-ui/FlatButton'
const styles = {
container: {
textAlign: 'center',
paddingTop: 200
}
}
class Index extends Component {
static getInitialProps ({ req }) {
}
constructor (props, context) {
super(props, context)
this.state = {
open: false
}
}
handleRequestClose = () => {
this.setState({
open: false
})
}
handleTouchTap = () => {
this.setState({
open: true
})
}
render () {
const standardActions = (
<FlatButton
label='Ok'
primary={Boolean(true)}
onClick={this.handleRequestClose}
/>
)
return (
<div style={styles.container}>
<Dialog
open={this.state.open}
title='Super Secret Password'
actions={standardActions}
onRequestClose={this.handleRequestClose}
>
1-2-3-4-5
</Dialog>
<h1>Material-UI</h1>
<h2>example project</h2>
<RaisedButton
label='Super Secret Password'
secondary
onClick={this.handleTouchTap}
/>
</div>
)
}
}
export default withMui(Index); //<--- just wrap the page
i have created github repository for you can use nextjs with material UI
https://github.com/hadnazzar/nextjs-materialui
Tutorial for adding material ui packages and how to create example components are described here
If you are experiencing flickering issues with older versions of material UI i suggest you to look at this article
yarn add #material-ui/core
_document.js
/* eslint-disable react/jsx-filename-extension */
import React from 'react';
import Document, {
Html, Main, NextScript,
} from 'next/document';
import { ServerStyleSheets } from '#material-ui/core/styles';
export default class MyDocument extends Document {
render() {
return (
<Html lang="en">
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
// `getInitialProps` belongs to `_document` (instead of `_app`),
// it's compatible with server-side generation (SSG).
MyDocument.getInitialProps = async (ctx) => {
// Render app and page and get the context of the page with collected side effects.
const sheets = new ServerStyleSheets();
const originalRenderPage = ctx.renderPage;
ctx.renderPage = () => originalRenderPage({
enhanceApp: (App) => (props) => sheets.collect(<App {...props} />),
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
// Styles fragment is rendered after the app and page rendering finish.
styles: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()],
};
};
_app.js
import React from 'react';
import PropTypes from 'prop-types';
import Head from 'next/head';
import { ThemeProvider } from '#material-ui/core/styles';
import CssBaseline from '#material-ui/core/CssBaseline';
import theme from '../src/theme';
export default function MyApp(props) {
const { Component, pageProps } = props;
React.useEffect(() => {
// Remove the server-side injected CSS.
const jssStyles = document.querySelector('#jss-server-side');
if (jssStyles) {
jssStyles.parentElement.removeChild(jssStyles);
}
}, []);
return (
<React.Fragment>
<Head>
<title>My page</title>
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
</Head>
<ThemeProvider theme={theme}>
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
<CssBaseline />
<Component {...pageProps} />
</ThemeProvider>
</React.Fragment>
);
}
MyApp.propTypes = {
Component: PropTypes.elementType.isRequired,
pageProps: PropTypes.object.isRequired,
};

Resources