I have tried multiple solutions that were suggested in MaterialUI and NextJS official examples and forums with no luck. My page is unable to use my MUI styles on the first render and I keep getting this error:
Warning: Prop `className` did not match. Server: "makeStyles-image-3 makeStyles-image-5" Client: "makeStyles-image-4 makeStyles-image-7"
My _document.tsx:
import React from 'react';
import Document, { DocumentContext, Head, Html, Main, NextScript } from 'next/document';
import { ServerStyleSheets } from '#material-ui/core/styles';
export default class MyDocument extends Document {
render() {
return (
<Html lang="en">
<Head>
<meta charSet="utf-8" />
<link rel="icon" href="/favicon.ico" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
static async getInitialProps(ctx: DocumentContext) {
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: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()] };
}
}
My _app.tsx:
import '../styles/globals.css';
import type { AppProps } from 'next/app';
import React, { useEffect } from 'react';
import { CssBaseline, ThemeProvider } from '#material-ui/core';
import Head from 'next/head';
import { theme } from '../src/app/theme';
const App: React.FC<AppProps> = ({ Component, pageProps }) => {
useEffect(() => {
const jssStyles = document.querySelector('#jss-server-side');
console.log(jssStyles?.parentElement?.removeChild(jssStyles));
jssStyles?.parentElement?.removeChild(jssStyles);
}, []);
return (
<React.Fragment>
<Head>
<title>My App</title>
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
</Head>
<ThemeProvider theme={theme}>
<CssBaseline />
<Component {...pageProps} />
</ThemeProvider>
</React.Fragment>
);
};
export default App;
The solutions I've tried:
https://github.com/mui-org/material-ui/blob/0ff9cb54a9/examples/nextjs-with-typescript/README.md
https://github.com/hadnazzar/nextjs-with-material-ui/blob/master/README.md
Also many from StackOverflow similar posts (though none of the answers helped, so please do not mark this as a duplicate).
Used packages versions:
"#material-ui/core": "^4.12.3",
"next": "11.1.2",
"react": "17.0.2",
Is there anything that I'm missing here?
Related
In the following segment of code I call the Header module and React automatically adds the import to the Header module.
import Head from 'next/head'
import Header from '../components/Header'
export default function Home() {
return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<Header/>
<main className={styles.main}>
</main>
</div>
)
}
But at compile time React tells me it cannot resolve the Header module:
error - ./pages/index.tsx:3:0
Module not found: Can't resolve '../components/Header'
Header.jsx
import Image from 'next/image'
import { useEffect, useState } from 'react'
import Link from 'next/link'
const Header = () => {
const [isScrolled, setIsScrolled] = useState(false);
useEffect(() => {
const handleScroll = () => {
if(window.scrollY > 0) {
setIsScrolled(true);
} else {
setIsScrolled(false);
}
}
window.addEventListener('scroll', handleScroll)
return () => {
window.removeEventListener('scroll', handleScroll)
}
}, [])
return (
<header>Header</header>
)
}
export default Header
Relative paths of index.jsx and Header.jsx:
\react\netflix-tailwind\components\Header.tsx
\react\netflix-tailwind\pages\index.tsx
I'm trying to pass a custom class using props to another component. It works absolutely fine on the dev mode but gets overridden on the production build.
Input Component
import React, { memo } from "react"
import injectSheet from "react-jss"
import styles from "./styles"
const Input = React.forwardRef((props, ref) => {
const {
classes,
value,
disabled,
type = "text",
accept,
placeholder,
required,
customClass = "",
pattern,
} = props
const handleChange = (e) => {
/* Logic */
}
return (
<input
ref={ref}
className={`${classes.container} ${customClass}`}
type={type}
accept={accept}
placeholder={placeholder}
value={value}
onChange={handleChange}
required={required}
disabled={disabled}
pattern={pattern}
/>
)
})
export default injectSheet(styles)(memo(Input))
Usage
<Input
type="email"
placeholder="Enter your email"
customClass={classes.customEmailInput}
onChange={setEmail}
highlight={emailError || isDisposableMail}
/>
Happening on production build
Here the customEmailInput class gets overridden
Moreover, I'm seeing some inconsistency with the class names, some classes appear with the prefix "Component" while some classes have the component name as the prefix. First reference Second reference. If I remove the forwardRef and memo from the Input component, then the class names get prefixed with the component name. Third reference
_app.js
import React from "react"
import Head from "next/head"
import { QueryClient, QueryClientProvider } from "react-query"
import { ThemeProvider } from "react-jss"
import { generateTheme } from "../theme"
import Header from "../components/shared/header"
const queryClient = new QueryClient()
const MyApp = (props) => {
const { Component, pageProps } = props
return (
<>
<Head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Title</title>
</Head>
<QueryClientProvider client={queryClient}>
<ThemeProvider theme={generateTheme()}>
<Header />
<Component {...pageProps} />
</ThemeProvider>
</QueryClientProvider>
</>
)
}
export default MyApp
_document.js
import Document, { Html, Head, Main, NextScript } from "next/document"
import { SheetsRegistry, JssProvider, createGenerateId } from "react-jss"
class MyDocument extends Document {
static async getInitialProps(ctx) {
const registry = new SheetsRegistry()
const generateId = createGenerateId()
const originalRenderPage = ctx.renderPage
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
(
<JssProvider registry={registry} generateId={generateId}>
<App {...props} />
</JssProvider>
),
})
const initialProps = await Document.getInitialProps(ctx)
return {
...initialProps,
styles: (
<>
{initialProps.styles}
<style
id="server-side-styles"
dangerouslySetInnerHTML={{ __html: registry.toString() }}
/>
</>
),
}
}
render() {
return (
<Html>
<Head>
<link rel="icon" href="/images/favicon.ico" />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
Plan - To render <List /> element in index.js. Displays the todo items the user has created.
Error -
./src/components/App.jsx
Attempted import error: './List' does not contain a default export (imported as 'List').
index.js -
import React from 'react';
import ReactDOM from 'react-dom';
import {List, Render} from './components/List';
import App from './components/App';
import '../src/styles.css';
ReactDOM.render(
<App />,
document.getElementById('root')
);
ReactDOM.render(
<Render />
, document.getElementById("list"));
List.jsx -
import react, { useRef } from 'react';
import ReactDOM from 'react-dom';
var todoItems = [];
const inputRef = useRef();
function onClick() {
todoItems.push(inputRef.current.value);
console.log("Pushed item in the array!");
render(inputRef.current.value);
}
function Render(value) {
todoItems.forEach(function a(item) {
<h1>{item}</h1>
});
}
function List() {
return (
<div className="mainbox">
<div className="inputdiv">
<input
type="text"
ref={inputRef}
placeholder="Enter Task..."
className="textbox"
id="taskName"
/>
<button className="button" onClick={onClick}>+</button>
</div>
</div>
);
}
export {List, Render};
I also tried -
export default List;
export {Render};
But it says useRef() cannot be called at the top level.
So I moved the inputRef to the List(), but it says that Render isn't defined.
Thanks!
P.S
After this import/export problem is solved, will the <h1> display?
function Render(value) {
todoItems.forEach(function a(item) {
<h1>{item}</h1>
});
}
EDIT -
index.html -
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link font-family: "Montserrat" , sans-serif;
href="https://fonts.googleapis.com/css?family=McLaren|Montserrat&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="../src/styles.css">
<title>Mandy's Todo-List App!</title>
</head>
<body>
<div id="root">
<div id="list">
</div>
</div>
</body>
</html>
import { useState, useEffect } from 'react';
function App() {
const [value, setValue] = useState('');
const [list, setList] = useState([]);
function handleChange(event) {
setValue(event.target.value);
}
function addTodo() {
setList([...list, value]);
}
useEffect(() => setValue(''), [list]);
return (
<div className='App'>
<input value={value} onChange={handleChange}/>
<button onClick={addTodo}>Add</button>
{list.map((item, index) => <h1 key={index}>{item}</h1>)}
</div>
);
}
export default App;
I am using material UI in NEXTJS and on first render sometimes its applying all the custom changes sometimes it doesn't. when it applying all those and click on link its breaking again and I did all the custom changes which mentioned https://github.com/mui-org/material-ui/blob/master/examples/nextjs here like creating custom _app.js and _document.js file
_app.js
import { useEffect, Fragment } from 'react';
import Head from 'next/head';
import PropTypes from 'prop-types';
import CssBaseline from '#material-ui/core/CssBaseline';
import { ThemeProvider } from '#material-ui/core/styles';
import theme from '../src/theme';
import "../styles/globals.css";
export default function MyApp({ Component, pageProps }){
useEffect(() => {
const jssStyles = document.querySelector('#jss-server-side');
console.log(jssStyles);
if (jssStyles) {
jssStyles.parentElement.removeChild(jssStyles);
}
}, []);
const getLayout = Component.getLayout || ((page) => page)
return (<>
<Head>
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
</Head>
<ThemeProvider theme={theme}>
<CssBaseline />
{getLayout(<Component {...pageProps} />)}
</ThemeProvider>
</>)
}
MyApp.propTypes = {
Component: PropTypes.elementType.isRequired,
pageProps: PropTypes.object.isRequired,
};
_document.js
import * as React from 'react';
import Document, { Html, Head, Main, NextScript } from 'next/document';
import theme from '../src/theme';
import { ServerStyleSheets } from '#material-ui/core/styles'
export default class MyDocument extends Document {
render() {
return (
<Html lang="en">
<Head>
{/* PWA primary color */}
<meta name="theme-color" content={theme.palette.primary.main} />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
// `getInitialProps` belongs to `_document` (instead of `_app`),
// it's compatible with static-site generation (SSG).
MyDocument.getInitialProps = async (ctx) => {
const originalRenderPage = ctx.renderPage;
const sheets = new ServerStyleSheets();
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) => <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()],
};
};
any help would appreciated
I'm stuck with this codes,
index.html
<!doctype html>
<html lang="en">
<head>
<title>React Redux Starter Kit</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
</head>
<body>
<div id="root" style="height: 100%"></div>
<div id="demo"></div>
</body>
</html>
Counter.js
import React from 'react'
import {core as Core} from 'zingchart-react'
export const Counter = React.createClass({
render () {
var myConfig = {
type: "bar",
series : [
{
values : [35,42,67,89,25,34,67,85,90.99]
}
]
};
return(
<div>Hello
<Core id="myChart" height="300" width="600" data={myConfig} />
</div>
)
}
})
export default Counter
main.js
import React from 'react'
import ReactDOM from 'react-dom'
import createBrowserHistory from 'history/lib/createBrowserHistory'
import { useRouterHistory } from 'react-router'
import { syncHistoryWithStore } from 'react-router-redux'
import createStore from './store/createStore'
import AppContainer from './containers/AppContainer'
import Counter from './components/Counter/Counter'
ReactDOM.render(<Counter/>, document.querySelector('#demo'));
// ========================================================
// Browser History Setup
// ========================================================
const browserHistory = useRouterHistory(createBrowserHistory)({
basename: __BASENAME__
})
// ========================================================
// Store and History Instantiation
// ========================================================
const initialState = window.___INITIAL_STATE__
const store = createStore(initialState, browserHistory)
const history = syncHistoryWithStore(browserHistory, store, {
selectLocationState: (state) => state.router
})
if (__DEBUG__) {
if (window.devToolsExtension) {
window.devToolsExtension.open()
}
}
const MOUNT_NODE = document.getElementById('root')
let render = (routerKey = null) => {
const routes = require('./routes/index').default(store)
ReactDOM.render(
<AppContainer
store={store}
history={history}
routes={routes}
routerKey={routerKey}
/>,
MOUNT_NODE
)
}
if (__DEV__ && module.hot) {
const renderApp = render
const renderError = (error) => {
const RedBox = require('redbox-react')
ReactDOM.render(<RedBox error={error} />, MOUNT_NODE)
}
render = () => {
try {
renderApp(Math.random())
} catch (error) {
renderError(error)
}
}
module.hot.accept(['./routes/index'], () => render())
}
render()
I am using react-redux starter kit - https://github.com/davezuko/react-redux-starter-kit, I'm getting this error, please help me out.
ERROR: Cannot read property '__reactAutoBindMap' of undefined
This is the es6 way of writing your component:
import React from 'react';
import {core as Core} from 'zingchart-react';
class Counter extends React.Component {
render () {
var myConfig = {
type: "bar",
series : [
{
values : [35,42,67,89,25,34,67,85]
}
]
};
return (
<div>Hello
<Core id="myChart" height="300" width="600" data={myConfig} />
</div>
)
}
}
export default Counter;
and to render it,
ReactDOM.render(<Counter />, document.getElementById('some_div'));
core is not a valid name for a React Component. React Components must start with an upper case letter, that is how React distinguish between components and HTML tags.
So your code should look like this
import React from 'react'
import {core as Core} from 'zingchart-react'
export const Counter = React.createClass({
render () {
var myConfig = {
type: "bar",
series : [
{
values : [35,42,67,89,25,34,67,85]
}
]
};
return (
<div>Hello
<Core id="myChart" height="300" width="600" data={myConfig} />
</div>
)
}
})
export default Counter
working example